答题思路:
需要在理解了递归的基础上进行,归并排序是将数列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。因此,可以在归并
排序中的合并过程中计算逆序数.
#include<stdio.h>
#include<stdlib.h>
int a[100001],t[100001];
long long num;
void sort(int b1,int e1,int b2,int e2)
{
int p=0,p1=b1,p2=b2;
while(p1<=e1&&p2<=e2)
{
if(a[p1]<=a[p2])
{
t[p++]=a[p1++];
}
else
{
t[p++]=a[p2++];
num+=e1-p1+1;//a[p1]>a[p2]那么从a[p1]到a[e1]都满足逆序对;
}
}
while(p1<=e1)
{
t[p++]=a[p1++];
}
while(p2<=e2)
{
t[p++]=a[p2++];
}
for(int i=b1;i<=e2;i++)
{
a[i]=t[i-b1];
}
}
void merge(int b,int e)
{
int m;
if(b<e)
{
m=(b+e)/2;
merge(b,m);
merge(m+1,e);
sort(b,m,m+1,e);
}
}
int main()
{
int i,n;
scanf("%d",&n);
num=0;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
merge(0,n-1);
printf("%lld\n",num);
}