题目就是让求 数组中,逆序数对的个数,比如说,,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后剩余的并入
}