题意:
给出你一个数字序列,让你输出用冒泡排序需要换多少次?
两个数(a, b)的排列,若满足a > b,则称之为一个逆序对。有多少个逆序对就要换多少次,又因为冒泡排序是从后往前面交换的,归并是分成了若干个有序对从left,mid+1进行比较的。是从前往后的比较交换的。这里的一个规律就是交换的个数是:也就是记录A序列找到第一个比B某一个大的数,他后面还余下的数的个数就是要交换的次数。
A:2 5 6 9
B:1 3 4 8
归并时,B中的1和A中2比,比他小,在冒泡中交换的次数就是A中第一个比1大的数后面的数字的个数,看看数据,读读这句话。个数是mid-i+1 ;
#include<stdio.h>
#include<string.h>
#define N 500004
long long res;
int b[N],a[N];//b为中间辅佐数组
void copy(int l,int r)
{
int i;
for(i=l;i<=r;i++)
a[i]=b[i];
}
void merge(int l,int mid,int r)
{
int i=l;
int j=mid+1;
int k=l;
while(i<=mid && j<=r)
{
if(a[i]<a[j])
{
b[k++]=a[i++];
}
else
{
b[k++]=a[j++];
res+=mid-i+1;
}
}
while(i<=mid)
{
b[k++]=a[i++];
}
while(j<=r)
{
b[k++]=a[j++];
}
}
void mergeSort(int l,int r)
{
if(l<r)
{
int mid=(l+r)/2;
mergeSort(l,mid);
mergeSort(mid+1,r);
merge(l,mid,r);
copy(l,r);
}
}
int main()
{
int n,i;
while(scanf("%d",&n)&&n)
{
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
res=0;
mergeSort(1,n);
printf("%lld\n",res);
}
return 0;
}