CPC23 2014-1 B.Crossings(求逆序数)
题目链接:http://acm.hrbust.edu.cn/
| B.Crossings | |||||
|
|||||
| 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了= =|||


浙公网安备 33010602011771号