NYOJ 117 求逆序数 (归并排序)
地址:http://acm.nyist.net/JudgeOnline/problem.php?pid=117
思路:归并排序,表示不太懂。。。。
算法分析:这个题的算法是利用归并排序的 merge() 函数,在处理在处理两段时,恰好要比较大小,顺便把逆数也求出来 故时间复杂度o(nlogn);
1 #include<stdio.h> 2 #include<stdlib.h> 3 #define N 1000010 4 long long ans; 5 int a[N]; 6 void merge(int s1,int e1,int s2,int e2) 7 { 8 int p1,p2,p; 9 int* temp = new int[e2-s1+5]; //归并为有序的temp ,此处定义temp 10 p=0;p1=s1;p2=s2; 11 while(p1<=e1&&p2<=e2) //将s1到e1和s2到e2合并到temp 12 { 13 if(a[p1]<=a[p2]) 14 { 15 temp[p++]=a[p1++]; 16 continue; 17 } 18 else 19 { 20 temp[p++]=a[p2++]; 21 ans+=e1-p1+1; //关键所在 22 continue; 23 } 24 } 25 while(p1<=e1) temp[p++]=a[p1++]; //将剩余的复制到temp 26 while(p2<=e2) temp[p++]=a[p2++]; 27 int i; 28 for(i=s1;i<=e2;i++) a[i]=temp[i-s1]; 29 delete temp; 30 } 31 32 void merge_sort(int s,int e) 33 { 34 int m; 35 if(s<e) 36 { 37 m=(s+e)/2; 38 merge_sort(s,m); 39 merge_sort(m+1,e); 40 merge(s,m,m+1,e); 41 } 42 } 43 44 int main() 45 { 46 int test; 47 scanf("%d",&test); 48 while(test--) 49 { 50 int n,i; 51 ans=0; 52 scanf("%d",&n); 53 for(i=0;i<n;i++) 54 scanf("%d",&a[i]); 55 merge_sort(0,n-1); 56 printf("%lld\n",ans); 57 } 58 }
用归并排序求逆序数。归并排序中适当的位置加上cnt+=n1-i,就可以了。