题目链接:https://www.luogu.com.cn/problem/P1908
题目描述
对于给定的一段正整数序列,求其中逆序对的数目。逆序对就是序列中 ai>aj且i<j的有序对。
分析
暴力法时间复杂度O(n2),数据规模大时不能AC。需要寻求一种分发高效的算法。考虑到逆序对也是一种有序对,可以采取一种边排序边计算的方法。归并排序是可以解决这个问题的。
#include<cstdio>
int a[500005],b[500005],n;
long long ans; //数据比较大,得用long long类型,防止溢出
void mergeSort(int left,int right){
if(left==right) return;
int mid=(left+right)/2;
mergeSort(left,mid); //递归算法
mergeSort(mid+1,right);
int i=left,j=mid+1,k=left;
while(i<=mid&&j<=right){
if(a[i]<=a[j]) b[k++]=a[i++];
else{
b[k++]=a[j++];
ans+=mid-i+1; //累计
}
}
while(i<=mid) b[k++]=a[i++];
while(j<=right) b[k++]=a[j++];
for(int i=left;i<=right;i++) a[i]=b[i]; //排序之后b[]赋值给a[]
}
int main() {
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
mergeSort(0,n-1);
printf("%lld",ans);
return 0;
}