在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。
如2 4 3 1中,2 1,4 3,4 1,3 1是逆序,逆序数是4。给出一个整数序列,求该序列的逆序数。
Input
第1行:N,N为序列的长度(n <= 50000)
第2 - N + 1行:序列中的元素(0 <= Aii <= 10^9)
Output
输出逆序数
Sample Input
4
2
4
3
1
Sample Output
4
对于这个题他就是一个典型的模板,我们理解了最好不理解就记下来也行(我觉得还是理解吧)毕竟这个还是基础的
#include <iostream> using namespace std; int a[500050]; int b[500050]; long long cnt;//注意次数可能爆掉 void merge(int *a, int first, int mid, int end) { int i, x; int y = mid+1; i = first; x = first; while((x<=mid) && (y<=end))//执行的条件是两部分都不能为空 { if (a[x]<=a[y]) { b[i++] = a[x++];//先赋值再下标下移 } else { cnt += mid-x+1;//每次左边剩下的数意味着存在左边比右边大的数,也就是存在逆序,再计数把所有左边数加起来就是整个数列的逆序数 b[i++] = a[y++]; } } /* 这一部分要注意,上面部分执行的条件是两部分都不能为空, 那么要是有一个空了,另一个必定没空,下面的代码就是处理这个问题。 一句话,就是把另一个没空的部 分全部接到已排好序的后面就行了。 刚开始我犯糊涂地疑问,为什么直接复制就可以了,万一剩下的部分是无序的呢? 但是我忽略了这已经是在合并了,是建立在子问 题已经解决的基础上的,所以剩下的部分必定是有序的啦。 */ while (x <= mid) //处理剩余数列 { b[i++] = a[x++]; } while (y <= end) { b[i++] = a[y++]; } while (first <= end) { a[first] = b[first]; first++; } } void merge_sort (int *a,int first, int end) { if (first < end) { int mid = first+ (end-first)/2; merge_sort(a,first,mid);//将问题分解,调用递归 merge_sort(a,mid+1,end); merge(a,first,mid,end);//合并的过程 } } int main () { int n; while (cin >> n && n) { cnt = 0; for (int i = 0; i< n;i++) { cin >> a[i]; } merge_sort(a,0,n-1); cout << cnt <<endl; } return 0; }