【演算法競賽進階指南】逆序對POJ2299Ultra-QuickSort
阿新 • • 發佈:2018-12-04
求逆序對需要用到的演算法是歸併排序,在排序的同時進行計算逆序對,改題目求冒泡的次數,實際上就是最少逆序對的個數,最小個數的話利用歸併排序中進行歸併的時候,如果左半邊有大於右半邊最小的值,能麼從該位置到左邊最後一個都與右半邊第一個構成逆序對,逆序對個數加上左邊個數,歸併排序利用遞迴,所以在本次排序的時候,左右半邊都已經有序了
注意歸併排序的演算法,需要再加強一下學習
void mergesort(int l,int r){ int mid=(l+r)>>1; int i=l,j=mid+1; for(int k=l;k<=r;k++){ if(j>r || (i<=mid && a[i]<a[j])) b[k]=a[i++]; else b[k]=a[j++]; } for(int k=l;k<=r;k++) a[k]=b[k]; } void merge(int l,int r){ int mid=(l+r)>>1; if(l<r){ merge(l,mid); merge(mid+1,r); mergesort(l,r); } }
上面是歸併排序的核心演算法,而下面是題目的程式碼
#include<iostream> #include<queue> #include<cstring> using namespace std; long long a[500005],b[500005],cnt; void mergesort(int l,int mid,int r){ int i=l,j=mid+1; for(int k=l;k<=r;k++){ if(j>r || (i<=mid && a[i]<a[j])) b[k]=a[i++]; else b[k]=a[j++],cnt+=mid-i+1; } for(int k=l;k<=r;k++) a[k]=b[k]; return; } void merge(int l,int r){ int mid=(l+r)>>1; if(l<r){ merge(l,mid); merge(mid+1,r); mergesort(l,mid,r); } return; } int main(){ int n; while(cin>>n&&n!=0){ cnt=0; for(int i=1;i<=n;i++) cin>>a[i]; merge(1,n); cout<<cnt<<"\n"; } return 0; }