Problem There is a permutation P with n integers from 1 to n. You have to calculate its inversion number, which is the number of pairs of Pi and Pj satisfying the following conditions: i<j and Pi>Pj. | ||
-
刚才去阿话QQ空间,看到他的以前的日至。7月8号和书记一起去广州市区玩的全部照片都被他上传了。也许对我来说,去一次市区也许就像和自己生一次气一样无足轻重吧,但在他眼里这么重要。
罢了。
以下是原文:
-
Sicily 1523 Inversion Number 解题报告 - [敲代码]
2008年10月23日
Time limit: 1 second(s) Memory limit: 32768 KBytes
Total Submit : 390 Accepted Submit : 95InputThe input may contain several test cases.
In each test case, the first line contains a positive integer n (n<=100000) indicating the number of elements in P. The following n lines contain n integers making the permutation P.
Input is terminated by EOF.OutputFor each test case, output a line containing the inversion number.Sample Input
Copy to clipboard5 3 4 1 5 2
Sample Output5
补注:这个题是利用了归并排序。如果想到归并排序,那基本不麻烦了。可气的是居然要用long long而不是int...
#include <iostream>
using namespace std;long long num[100005], n, i, mycount, tmp[100005];
void mergeSort(long long num[], long long left, long long right)
{
if (left == right)
{
return;
}
long long mid = (left+right)/2;
mergeSort(num, left, mid);
mergeSort(num, mid+1, right);
long long pos = left, i = left, j = mid+1;
while (true)
{
if (num[i] < num[j])
{
tmp[pos] = num[i];
i++;
}
else
{
tmp[pos] = num[j];
j++;
mycount += (mid-i+1);
}
pos++;
if (pos > right || i > mid || j > right)
{
break;
}
}
for (; i <= mid; i++, pos++)
{
tmp[pos] = num[i];
}
for (; j <= right; j++, pos++)
{
tmp[pos] = num[j];
}
for (i = left; i <= right; i++)
{
num[i] = tmp[i];
}
}int main()
{
while (cin >> n)
{
if (n == 0)
{
long long a[1];
a[2] = 1;
printf("0\n");
continue;
}
mycount = 0;
for (i = 0; i < n; i++)
{
cin >> num[i];
}
mergeSort(num, 0, n-1);
cout << mycount << endl;
}
return 0;
} -
Sicily 1045 Space Management 解题报告 - [敲代码]
2008年10月11日
ProblemThe new general manager Gill Bates has been to a seminar on time management. Ever since she has been bothering all of her staff to manage their own time. Now she plans to take it one step further: she wants to start managing her space too. And since she has also learned to start small, she wants to start by managing her desk space. Work tends to pile up on her desk, especially since the time management training where she was taught to order all documents in neat piles and organize her work accordingly. She now needs to calculate how much desk space is occupied. For this she comes up with a cunning plan. First, she orders her staff to measure the size and exact location of each document on the desk, in tenths of millimeters accuracy. As Gill is a very tidy person, all her document are completely on her desk, and are all perfectly aligned to the edges of the desk (i.e. the edges of all documents are parallel to an edge of the desk). For each document, the staff writes down the position of the lower left corner of the document and its size.
What you need to do now is to write a program that, given the input from the staff, calculates the occupied space on the desk. The maximum size of the desk is 2 * 1 meters. There is a maximum of 500 documents on the desk.InputThe first line of the input consists of the number N of desks to be considered. Next follows for each desk the number of documents. Then follows for each document a separate line with 4 numbers: the smallest X and Y co-ordinates (i.e. the lower left corner), and the width and height of the document respectively.OutputThe output consists of N lines containing the amount of occupied space on each desk in squared tenths of millimeters.Sample Input2 2 0 0 1000 1000 0 0 1000 1000 3 0 0 2 2 2 2 2 2 1 1 2 2
Sample Output1000000 10
补注:牛人就是牛人,WXYZ过来几句描述就让人豁然开朗。当你进入一个矩形时,标记该侧面为1,出的时候标记为-1.这样统计时从左向右每当flag大于0便意味着这块桌子被文件覆盖了。
#include <iostream>
#include <memory.h>
using namespace std;int m[2000][1000];
int main()
{
int n, t, i, j, k, p0x, p0y, p1x, p1y, flag, count;
scanf("%d", &t);
while (t--)
{
memset(m, 0, sizeof(m));
scanf("%d", &n);
for (k = 0; k < n; k++)
{
scanf("%d%d%d%d", &p0x, &p0y, &p1x, &p1y);
p1x += p0x;
p1y += p0y-1;
for (i = p0y; i <= p1y; i++)
{
m[p0x][i] += 1;
m[p1x][i] += -1;
}
}
flag = count = 0;
for (i = 0; i < 1000; i++)
{
for (j = 0; j < 2000; j++)
{
flag += m[j][i];
//m[j][i] = 0;
if (flag > 0)
{
count++;
}
}
flag = 0;
}
printf("%d\n", count);
}
return 0;
} -
Sicily 1342 开心的金明 解题报告(1342采药与这道题基本一致) - [敲代码]
2008年09月20日
Problem金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行”。今天一早金明就开始做预算,但是他想买的东西太多了,肯定会超过妈妈限定的N元。于是,他把每件物品规定了一个重要度,分为5等:用整数1~5表示,第5等最重要。他还从因特网上查到了每件物品的价格(都是整数元)。他希望在不超过N元(可以等于N元)的前提下,使每件物品的价格与重要度的乘积的总和最大。 设第j件物品的价格为v[j],重要度为w[j],共选中了k件物品,编号依次为j1,j2,……,jk,则所求的总和为: v[j1]*w[j1]+v[j2]*w[j2]+ …+v[jk]*w[jk]。(其中*为乘号)请你帮助金明设计一个满足要求的购物单。
Input输入包含多个测试数据。
每个测试数据的第1行,为两个正整数,用一个空格隔开:
N m
(其中N(<30000)表示总钱数,m(<25)为希望购买物品的个数。)
从第2行到第m+1行,第j行给出了编号为j-1的物品的基本数据,每行有2个非负整数
v p(其中v表示该物品的价格(v<=10000),p表示该物品的重要度(1~5))
Output对于每个测试数据输出一行,其中只含有一个正整数,为不超过总钱数的物品的价格与重要度乘积的总和的最大值(<100000000)。
Sample Input1000 5 800 2 400 5 300 5 400 3 200 2 1000 5 800 2 400 5 300 5 400 3 200 2
Sample Output3900 3900
补助:阿话跟我说,这道题需要动态规划(DP,一开始我把DP理解成了深度优先搜索)。无语。
#include <iostream>
using namespace std;int matrix[25][30000];
int main()
{
int total_money, googs_count, i, j, cost[25], get[25], min_money;
while (scanf("%d%d", &total_money, &googs_count) != EOF)
{
memset(matrix, 0, sizeof(matrix));
min_money = INT_MAX;
for (i = 1; i <= googs_count; i++)
{
scanf("%d%d", &cost[i], &get[i]);
get[i] *= cost[i];
if (cost[i] < min_money)
{
min_money = cost[i];
}
}
for (i = 1; i <= googs_count; i++)
{
for (j = min_money; j <= total_money; j++)
{
matrix[i][j] = matrix[i-1][j];
if (j >= cost[i])
{
if (matrix[i-1][j-cost[i]] + get[i] > matrix[i][j])
{
matrix[i][j] = matrix[i-1][j-cost[i]] + get[i];
}
}
}
}
printf("%d\n", matrix[googs_count][total_money]);
}
return 0;
} -
Sicily 1522 Connection 解题报告 - [敲代码]
2008年09月18日
Problem:There are N cities in the country and M bidirectional roads between the cities. The government wants to build some new roads such that for any pair of cities there is at least one path between them. Now you have to find out the minimal amount of roads that have to build.InputThe input may contain multiple test cases.
For each test case, the first line is two integers N (1<=N<=100) and M (1<=M<=N*N/2), indicating the number of cities and the number of roads. Then the next M lines each contain two integers x and y (0<=x,y<n), meaning that there is a road between cities x and cities y.
N=M=0 indicates the end of input.OutputFor each test case, print the answer in a single line.Sample Input5 2 0 1 2 3 0 0
Sample Output2
补注:刚才在看数据结构里面图论的相关东西,想到了这道题目,就做了一下,深度优先搜索,没想象中的那么可怕。大概也算是个新的开始吧。
#include <iostream>
using namespace std;void DFS(int i, bool ref[], int matrix[], int n)
{
if (ref[i] == true)
{
return;
}
ref[i] = true;
int j;
for (j = 0; j < n; j++)
{
if (matrix[100*i+j] && !ref[j])
{
DFS(j, ref, matrix, n);
}
}
return;
}int main()
{
int n, m, matrix[10000], i, j, k, count;
while (scanf("%d%d", &n, &m), n != 0 || m != 0)
{
count = 0;
memset(matrix, 0, sizeof(matrix));
for (i = 0; i < m; i++)
{
scanf("%d%d", &j, &k);
matrix[100*j+k] = matrix[100*k+j] = 1;
}
for (i = 0; i < n; i++)
{// Warshall algorithm start;
for (j = 0; j < n; j++)
{
for (k = 0; k < n; k++)
{
if (k == j)
{
continue;
}
else
{
matrix[100*j+k] = matrix[100*j+k] || (matrix[100*j+i] && matrix[100*i+k]);
}
}
}
}// Warshall algorithm end;
bool ref[100];
for (i = 0; i < n; i++)
{
ref[i] = false;
}//初始化使得一开始所有点都没被访问过
for (i = 0; i < n; i++)
{
if (ref[i])
{
continue;
}
else
{
if (i != 0)
{
count++;
}
DFS(i, ref, matrix, n);
}
}
printf("%d\n", count);
}
return 0;
}







