输入一个序列求序列中的逆序对
归并排序代码
void merge_sort(int *a,int x,int y,int *T)
{
if(y-x<=1)return ;
int m=x+(y-x)/2;
int p=x,q=m,i=x;
merge_sort(a,x,m,T);
merge_sort(a,m,y,T);
while(p<m||q<y)
{
if(q>=y||(p<m&&a[p]<=a[q]))
T[i++]=a[p++];
else
T[i++]=a[q++];
}
for(int x;i<y;i++)a[i]=T[i];
}
//代码来自紫书
分治方法,先分开,然后递归求解,最后合并问题。
将序列分成差不多等长的两部分,统计i和j均在左边或者均在右边的逆序对数,再统计i在左边,j在右边的逆序对数。
求i,j分别在两边的情况,可以通过上面的排序算法所用的技巧算,因为归并排序最后合并i在左j在右,并且两边有序所以每一次找到a[p]>a[q]就可以判定为是逆序,并且可以判定a[p]到a[m]中间的都大于a[q]。于是 可以直接cnt+=m-p。
#include<iostream>
using namespace std;
int a[100];
int t[100];
int cnt=0;
void merge_sort(int *a,int x,int y,int *T)
{
if(y-x>1)
{
int m=x+(y-x)/2;
int p=x,q=m,i=x;
merge_sort(a,x,m,T);
merge_sort(a,m,y,T);
while(p<m||q<y)
{
if(q>=y||(p<m&&a[p]<=a[q]))
T[i++]=a[p++];
else
{T[i++]=a[q++];cnt+=m-p;}
}
for(i=x;i<y;i++)
a[i]=T[i];
}
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
merge_sort(a,0,n,t);
cout<<cnt<<endl;
}
//代码来自对紫书上修改