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;
}

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