逆序对是指数列a[1],a[2],a[3]…中的任意两个数a[i],a[j] (i<j),如果a[i]>a[j],那么我们就说这两个数构成了一个逆序对。
而归并排序的合并两个排列的过程中
会将右边的有序序列的元素依次插入前面的 有序序列
如(3 7 12) ( 5 6 8)
将5 插入 (3 7 12) 中
因为后面有序 所以 假设 5和左边全部元素构成逆序对 所以有mid+1
而左边序列又有start1 个数比5 小 所以 逆序数就是 mid+1-start1
这样就能大大缩减 计算逆序数对的时间。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[500005],b[500005];
long long ans;
void merge(int left,int mid,int right)
{
int start1=left,start2=mid+1;
int num=left;
int i;
while(start1<=mid&&start2<=right)
{
if(a[start1]>a[start2])
{
ans=ans+mid-start1+1;
b[num++]=a[start2++];
}
else
b[num++]=a[start1++];
}
while(start1<=mid)
b[num++]=a[start1++];
while(start2<=right)
b[num++]=a[start2++];
for(i=left; i<=right; i++)
a[i]=b[i];
return;
}
void mergesort(int left,int right)
{
int mid=(left+right)/2;
if(left<right)
{
mergesort(left,mid);
mergesort(mid+1,right);
merge(left,mid,right);
}
return;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
ans=0;
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
mergesort(1,n);
printf("%lld\n",ans);
}
return 0;
}