poj 2299 Ultra-QuickSort (归并排序,逆序数)

链接:poj 2299

题意:给出长度为n的序列,每次只能交换相邻的两个元素,

问至少要交换几次才使得该序列为递增序列

分析:冒泡排序每次只能交换相邻两个元素,也就是求

用冒泡排序使其为递增序列的交换次数,每交换一次记录一次就好

但是这题数据较大,冒泡排序效率比较低,会超时的

这里就可以利用归并排序了,用归并排序可以求序列的逆序数

而一个序列的 逆序数 = 只允许相邻两个元素交换时,得到有序序列的交换次数

 

#include<stdio.h>
#include<stdlib.h>
#define M 500000
int a[M+5],l[M+5],r[M+5];
__int64 t;
void cmp(int ll,int mid,int rr)
{
    int m=0,n=0,i,j,k;
    for(i=ll;i<=mid;i++)
        l[m++]=a[i];
    for(i=mid+1;i<=rr;i++)
        r[n++]=a[i];
    i=j=0;
    k=ll;
    while(i<m&&j<n){
        if(l[i]<=r[j])
            a[k++]=l[i++];
        else{
            a[k++]=r[j++];
            t+=m-i;   //计算逆序数
        }
    }
    while(i<m)
        a[k++]=l[i++];
    while(j<n)
        a[k++]=r[j++];
}
void mergesort(int l,int r)
{
    int mid;
    if(l<r){
        mid=(l+r)/2;
        mergesort(l,mid);
        mergesort(mid+1,r);
        cmp(l,mid,r);
    }
}
int main()
{
    int n,i;
    while(scanf("%d",&n)&&n){
        for(i=0;i<n;i++)
            scanf("%d",&a[i]);
        t=0;
        mergesort(0,n-1);
        printf("%I64d\n",t);
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章