题目就是让求 数组中,逆序数对的个数,比如说,,9,1,0,5,4 就有(9,1) (9,0)(9,4)(9,5) (1,0) (5,4) 6对;
如果直接暴力搜索的话, O(n^2) 会超时;借用归并排序的 高效性,以及过程也是比较大小,便可以用来求逆序数对; 可以直接套用 归并排序的模版来用,
注意几个问题 : 这个题 ,数据量比较大, 最后结果是 long long 型的, 然后大数组最好都是在main()函数外面 ;
代码:
#include <stdio.h> long long ans; int List[500005],n; int templist[500005]; void MergeSort(int List[] ,int n); void MergePass(int initList[],int mergedList[],int len); void merge(int initList[],int mergedList[],int left,int mid, int right); int main() { while(scanf("%d",&n)) { if(!n) break; ans=0; for(int i=0;i<n;i++) scanf("%d",&List[i]); MergeSort(List,n); printf("%lld\n",ans); } } void MergeSort(int List[] ,int n) { int len=1; while(len<n) { MergePass(List,templist,len); len*=2; MergePass(templist,List,len); len*=2; } } void MergePass(int initList[],int mergedList[],int len) { int i = 0; while (i+2*len-1 <= n-1) { merge( initList, mergedList,i, i+len-1, i+2*len-1); i += 2 * len; } if ( i+len <= n-1 ) merge( initList, mergedList, i, i+len-1, n-1); else for ( int j = i; j <= n-1; j++) mergedList [j] = initList[j]; } void merge(int initList[],int mergedList[],int left,int mid, int right) { int i = left, j = mid+1, k = left; while ( i <= mid && j <= right ) //两两比较将较小的并入 if ( initList[i] <= initList[j] ) { mergedList [k] = initList[i]; i++; k++; } else { mergedList [k] = initList[j]; ans+=mid-i+1;j++; k++; } while ( i <= mid ) { mergedList[k] = initList[i]; i++; k++; }//将mid前剩余的并入 while ( j <= right ) { mergedList[k] = initList[j]; j++; k++; } //将mid后剩余的并入 }