求逆序数
时间限制:
2000 ms | 内存限制:
65535 KB
难度:
5
-
描述
-
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。
现在,给你一个N个元素的序列,请你判断出它的逆序数是多少。
比如 1 3 2 的逆序数就是1。
-
输入
-
第一行输入一个整数T表示测试数据的组数(1<=T<=5)
每组测试数据的每一行是一个整数N表示数列中共有N个元素(2〈=N〈=1000000)
随后的一行共有N个整数Ai(0<=Ai<1000000000),表示数列中的所有元素。
数据保证在多组测试数据中,多于10万个数的测试数据最多只有一组。
输出
- 输出该数列的逆序数 样例输入
-
2 2 1 1 3 1 3 2
样例输出
-
0 1
分析:一开始是用dp求以当前数结尾的最长上升子序列的长度,然后相加得到结果,结果超时了。最后看了学长的代码,用归并排序做的,详解在大白书143页。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <queue> #include <vector> using namespace std; const int MAXN = 5000000 + 10; long long cnt; int n; int a[MAXN], t[MAXN]; void merge_sort(int* A, int x, int y, int* T) { if (y - x > 1) { int m = x + (y - x) / 2; ///划分 int p = x, q = m, i = x; merge_sort(A, x, m, T); ///递归求解 merge_sort(A, m, y, T); ///递归求解 while (p < m || q < y) { ///从左半数组复制到临时空间 if (q >= y || (p < m && A[p] <= A[q])) T[i++] = A[p++]; else { T[i++] = A[q++]; ///从左半数组复制到临时空间 cnt += m - p; ///累加 } } for ( i = x; i < y; i++) A[i] = T[i]; ///从辅助空间复制回A数组 } } int main() { int cont; scanf("%d",&cont); while(cont--) { scanf("%d",&n); for (int i = 0; i < n; i++) scanf("%d", &a[i]); cnt = 0; merge_sort(a, 0, n, t); printf("%lld\n", cnt); //for(int i = 0;i < n;i++) //printf("%d ",a[i]); //printf("\n"); } return 0; }
-
第一行输入一个整数T表示测试数据的组数(1<=T<=5)