归并排序是将数列a[l,h]分成两半a[l,mid]和a[mid+1,h]分别进行归并排序,然后再将这两半合并起来。
在合并的过程中(设l<=i<=mid,mid+1<=j<=h),当a[i]<=a[j]时,并不产生逆序数;当a[i]>a[j]时,在
前半部分中比a[i]大的数都比a[j]大,将a[j]放在a[i]前面的话,逆序数要加上mid+1-i。因此,可以在归并
排序中的合并过程中计算逆序数.复杂度为nlogn.树状数组也可以求.以后再补充。。。
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
#define ll long long
const int N = 5e5+5;
ll ans;
int a[N],tp[N],n;
void mg(int arr[],int l,int r){
int m=(l+r)/2,i=l,j=m+1,k=1;
while(i<=m&&j<=r){
if(arr[i]<=arr[j]){
tp[k++]=arr[i++];
}else {
ans+=(m-i+1);
tp[k++]=arr[j++];
}
}
while(i<=m) tp[k++]=arr[i++];
while(j<=r) tp[k++]=arr[j++];
for(int i=1;i<k;i++)
arr[l++]=tp[i];
}
void mgsort(int arr[],int l,int r){
if(l>=r) return ;
else {
int m=(l+r)/2;
mgsort(arr,l,m);
mgsort(arr,m+1,r);
mg(arr,l,r);
}
}
int main(){
while(~scanf("%d",&n)&&n){
ans=0;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
mgsort(a,1,n);
printf("%lld\n",ans);
}
}