求逆序对数

描述

对于一个长度为N的整数序列A,满足i < j 且 Ai > Aj.的数对(i,j)称为整数序列A的一个逆序
请求出整数序列A的所有逆序对个数

输入

输入包含多组测试数据,每组测试数据有两行
第一行为整数N(1 <= N <= 20000),当输入0时结束
第二行为N个整数,表示长为N的整数序列

输出

每组数据对应一行,输出逆序对的个数

样例输入

1
2
3
4
5
6
7
5
1 2 3 4 5
5
5 4 3 2 1
1
1
0

样例输出

1
2
3
0
10
0

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <cstdio>
#include <iostream>

using namespace std;

int src[100000];
int dst[100000];
int res;

void mergesort(int a, int b)
{
if ((b - a) <= 1) {
return;
}
mergesort(a, (a + b + 1) / 2);
mergesort((a + b + 1) / 2, b);
int x = a;
int y = (a + b + 1) / 2;
int z = a;
while ((x < (a + b + 1) / 2) && (y < b)) {
// 最重要的一步: Count
if (src[x] > src[y]) {
// x以及x之后的都是逆序对
res += (a + b + 1) / 2 - x;
dst[z++] = src[y++];
}
else {
dst[z++] = src[x++];
}
}
// 后面的不可能再有逆序对了,因为前面都算过了
while (x < (a + b + 1) / 2) {
dst[z++] = src[x++];
}
while (y < b) {
dst[z++] = src[y++];
}
// 复制一下
for (int i = a; i < b; i++) {
src[i] = dst[i];
}
}

int main(void)
{
int n;
scanf("%d", &n);
while (n > 0) {
res = 0;
for (int i = 0; i < n; i++) {
scanf("%d", &src[i]);
}
mergesort(0, n);
printf("%d\n", res);
scanf("%d", &n);
}
return 0;
}

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×