逆序对

输入一个序列求序列中的逆序对

归并排序代码

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;
}
//代码来自对紫书上修改

 

posted @ 2018-08-13 19:29  ke_yi  阅读(110)  评论(0编辑  收藏  举报