求逆序数
时间限制:
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
归并排序执行过程:
1、执行归并排序函数时,把全部的数字一分为二,继续递归调用函数自身,左一半右一半的划分开,直到每一份里只有一个元素为止,停止划分。
2、把划分开的元素按照大小顺序排列,先 1 1,合并为个数为 2 的数组,再把 2 2 按顺序大小要求合并成个数为 4 的数组,依次进行把所有元素按大小排序
两两合并时两序列均已是有序序列
如:
4 1 3 10 7 3 5 0
4 1 3 10 7 3 5 0
4 1 3 10 7 3 5 0
4 1 3 10 7 3 5 0 //每一组个数为 1 结束
合并: 1 4 3 10 3 7 0 5
1 3 4 10 0 3 5 7
最后结果: 0 1 3 3 4 5 7 10
本题利用归并时比较大小条件,因为两序列合并时都已经是有序的,所以一旦遇到前一个序列的a比后一个序列中的一个值大,那么前一个序列数的值a以后的数(包括a)都比后序列的值大,所以sum += (p3-s1+1); sum用long long.
代码如下:1 2 //归并排序 3 4 #include <stdio.h> 5 #include <stdlib.h> 6 long long sum = 0; 7 void mergesort(int a[],int ,int ); 8 int main() 9 { 10 int a[1000300]; 11 int T,n,i; 12 scanf("%d",&T); 13 while(T--) 14 { 15 sum = 0; 16 scanf("%d",&n); 17 for(i=0;i<n;i++) 18 scanf("%d",&a[i]); 19 mergesort(a,0,n-1); 20 21 printf("%lld\n",sum); 22 } 23 return 0; 24 } 25 26 void merge(int a[],int s1,int e1,int s2,int e2) 27 { 28 //s1-e1为左数组 29 //s2-e2为右数组 30 int j = 0,i,p1 = s1,p2 = e2,p3 = e1; 31 int *temp = (int*)malloc(sizeof(int)*(e2-s1+5)); 32 33 while(s1 <= e1 && s2 <= e2) 34 { 35 if(a[s1] <= a[s2]) 36 { 37 temp[j++] = a[s1++];continue; 38 } 39 else 40 { 41 sum += (p3-s1+1); 42 temp[j++] = a[s2++];continue; 43 } 44 } 45 while(s1 <= e1)//如果左边还有 46 temp[j++] = a[s1++]; 47 48 while(s2 <= e2)//如果右边还有 49 temp[j++] = a[s2++]; 50 51 j = 0; 52 for(i = p1;i <= p2;i++)//把排好序的数组存回原来的地方 53 a[i] = temp[j++]; 54 55 delete temp;//记得释放指针 56 } 57 void mergesort(int a[],int left,int right) 58 { 59 //先一直拆分左边,知道拆分的只剩下一个元素为止,然后以一个元素为对称,右边也只有一个元素,然后合并两个元素 60 //一直这样向上合并,先1 1合并,然后2 2 合并 4 4..8 8..16 16...知道所有元素都已经合并完成 61 //带合并的两列数字都已经是有序的 62 int mid; 63 if(left < right) 64 { 65 mid = (left+right)/2; 66 mergesort(a,left,mid);//左拆分 67 mergesort(a,mid+1,right);//右拆分 68 69 merge(a,left,mid,mid+1,right);//合并 70 } 71 } 72