归并排序实现求逆序数

来源:互联网 发布:xfun吃货俱乐部淘宝 编辑:程序博客网 时间:2024/06/07 21:56

思路:归并排序是每次将数组分成更小的几个数组进行归并。而每一次归并都是把a[i] a[j](low<=i<=mid<j<=high)较小放入数组temp。易知如果a[i]>a[j],则需要把a[j]放到a[i]的前面,而原本排在a[i]后的元素又大于a[i],所以逆序数就是+=mid-i+1。

对于本题:交换相邻的元素的位置就是求对应逆序数的多少。一个在后面的数放到前面交换的次数=这个元素之前的逆序数个数。

poj1804

#include<cstdio>#include<cstring>#include<iostream>using namespace std;const int maxn=1e3+50;int casenum,n,a[maxn],cnt,temp[maxn];void unite(int a[],int low,int mid,int high){    int i=low,j=mid+1,k=low;    while(i<=mid&&j<=high){    if(a[i]<=a[j]){        temp[k++]=a[i++];    }    else{        temp[k++]=a[j++];        cnt+=mid-i+1;///if a[i]>a[j] then the element after(larger than) a[i] is also larger than a[j]    }    }    while(i<=mid) temp[k++]=a[i++];    while(j<=high) temp[k++]=a[j++];    for(int i=low;i<=high;i++)    a[i]=temp[i];}void MergeSort(int a[],int low,int high){    if(low<high){        int mid=(low+high)>>1;        MergeSort(a,low,mid);        MergeSort(a,mid+1,high);        unite(a,low,mid,high);    }}int main(){        scanf("%d",&casenum);        for(int i=1;i<=casenum;i++){          cnt=0;          memset(a,0,sizeof(a));          memset(temp,0,sizeof(temp));          scanf("%d",&n);         for(int j=1;j<=n;j++)            scanf("%d",&hga[j]);            MergeSort(a,1,n);            printf("Scenario #%d:\n",i);            printf("%d\n\n",cnt);            /*for(int i=1;i<=n;i++)                cout<<a[i]<<endl;*/        }    return 0;}

原创粉丝点击