poj2299
题意:求逆序对(即有几个[i,j]使得i<j且a[i]>a[j])
做法:归并排序
在排序时,对于a[i]>a[j](i<j)记录个数+=m-i+1个逆序对(排序前面的比a[i]小的数个数)
可以看代码
优化:在进行归并排序时,可以通过记录指针的方式减少复制的次数(nlgn次变为n次,在开头执行即可),具体参见代码
#include<stdio.h> #include<string.h> int a[500010],b[500010],n; long long sum=0; inline int max(int* a,int& i,int& j){ if(a[i]<a[j]) return a[i++]; else return a[j++]; } void MergeSort(int l,int r,int* a,int* b){ if(l==r) return; int m=(l+r)>>1,i,j,k; MergeSort(l,m,b,a); MergeSort(m+1,r,b,a); for(i=l,j=m+1,k=i;i<=m&&j<=r;b[k++]=max(a,i,j)) if(a[i]>a[j]) sum+=m-i+1; //这里统计逆序对个数 for(;i<=m;b[k++]=a[i++]); for(;j<=r;b[k++]=a[j++]); //这里可以省略 for i=l~r a[i]=b[i] 加快排序速度 } int main(){ for(;scanf("%d",&n)&&n;MergeSort(0,n-1,a,b),printf("%lld\n",sum)) for(int i=sum=0;i<n;++i) scanf("%d",a+i),b[i]=a[i]; }