您的位置:首页 > 其它

CPC23 2014-1 B.Crossings(求逆序数)

2014-11-11 22:14 190 查看
题目链接:http://acm.hrbust.edu.cn/

B.Crossings
Time Limit: 3000 MSMemory Limit: 32768 K
Total Submit: 349(65 users)Total Accepted: 38(38 users)Special Judge: No
Description
Given a permutation P of {0, 1, ..., n − 1}, we define the crossing number of it as follows. Write the sequence 0, 1, 2, .
. . , n − 1 from left to right above the sequence P(0), P(1), . . . , P(n − 1). Draw a straignt line from 0 in the top line to 0 in the bottom line, from 1 to 1, and so on. The crossing number of P is the number of pairs of lines that cross. For example, if
n = 5 and P = [1, 3, 0, 2, 4], then the crossing number of P is 3, as shown in the figure below:



In this problem a permutation will be specified by a tuple (n, a, b), where n is a prime and a and b are integers (1<=a<=n-1 and 0<=b<=n-1).
We call this permutation Perm(n, a, b), and the ith element of it is (a*i+b) mod n (with i in the range [0, n − 1]). So the example above is specified by Perm(5, 2, 1).

Input
There are several test cases in the input file. Each test case is specified by three space-separated numbers n, a, and b on a line. The
prime n will be at most 1,000,000. The input is terminated with a line containing three zeros.
Output
For each case in the input print out the case number followed by the crossing number of the permutation.Follow the format in the example
output.
Sample Input
5 2 1
19 12 7
0 0 0
Sample Output
Case 1: 3
Case 2: 77
题目大意:通过如题所述变换,如图,求交叉点个数。
由于通过变换位置得到的交叉,提到前面的数字自然会与放在后面的数字形成交叉,也就是求逆序数即可。

采用归并排序nlog(n)的求逆序数方式可过。

AC代码(2443ms):

#include <cstdio>
#define MAXN 1000010
using namespace std;
typedef long long LL;
LL n, x, y;
LL a[MAXN], tmp[MAXN];
long long result;
void merge(int l, int mid, int r) {
int i, j, k;
i = l, j= mid + 1, k = 1;
while(i<= mid && j <= r) {
if(a[j] < a[i]) {
tmp[k++] = a[j++];
result += mid - i + 1;
} else
tmp[k++] = a[i++];
}
while(i <= mid)  tmp[k++] = a[i++];
while(j <= r) tmp[k++] = a[j++];
for(i = l, k = 1; i<= r; i++, k++)
a[i] = tmp[k];
}
void merge_sort(int l, int r) {
if(l < r) {
int mid = (l + r) / 2;
merge_sort(l, mid);
merge_sort(mid + 1, r);
merge(l, mid, r);
}
}
int main() {
int cnt = 0;
while(~scanf("%lld%lld%lld", &n, &x, &y)) {
if(n == 0) break;
for(int i = 1; i <= n; i++) {
a[i] = (x * (LL)(i - 1) + y) % n;
}
result = 0LL;
merge_sort(1, n);
printf("Case %d: %lld\n", ++cnt, result);
}
return 0;
}


PS:此题可能是卡了下线段树的常数2nlog(n),导致T了= =|||
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: