原理:可以用归并排序计算逆序对数,在归并排序中的交换次数就是这个序
列的逆序对数:归并排序是将序列a[l, r]分成两个序列a[l, mid]和a[mid
- 1, r],分别进行归并排序,然后再将这两个有序序列进行归并排序,
在归并排序的过程中,设l<=i<=mid,mid+1<=j<=r,当a[i]<=a[j]时,并不产生逆序对数;而当a[i]> a[j]时,则在有序序列a[l, mid]中,在a[i]后面的数
都比a[j]大,将a[j]放在a[i]前,逆序对数就要加上mid-i+1。
#include<iostream>
using namespace std;
int ans;
void merge(int * s,int *temp,int l,int mid,int r)
{
int a=l;
int b=mid+1;
int k=0;
while(a<=mid && b<=r)
{
if(s[a]<=s[b])
temp[k++]=s[a++];
else
{
ans+=(mid-a+1);
temp[k++]=s[b++];
}
}
while(a<=mid)
temp[k++]=s[a++];
while(b<=r)
temp[k++]=s[b++];
int begin=l;
for(int i=0;i<k;i++)
{
s[begin++]=temp[i];
}
}
void mergeSort(int * s,int * temp,int l,int r)
{
if(l==r)
return ;
int mid=(l+r)/2;
mergeSort(s,temp,l,mid);
mergeSort(s,temp,mid+1,r);
merge(s,temp,l,mid,r);
}
int cases,n;
int main()
{
int s[1005];
int temp[1005];
cin>>cases;
int xh=1;
while(cases--)
{
ans=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&s[i]);
}
mergeSort(s,temp,0,n-1);
printf("Scenario #%d:\n",xh++);
printf("%d\n\n",ans);
}
return 0;
}