歸併排序(求逆序對)
阿新 • • 發佈:2018-12-21
#include<bits/stdc++.h> using namespace std; void merge(int a[],int first,int mid,int last,int temp[]) { int i=first,j=mid+1; int m=mid,n=last; int k=0; while(i<=m&&j<=n) { if(a[i]<a[j]) temp[k++]=a[i++]; else temp[k++]=a[j++]; } while(i<=m) temp[k++]=a[i++]; while(j<=n) temp[k++]=a[j++]; for(i=0;i<k;i++) a[first+i]=temp[i]; } void mergesort(int a[],int first,int last,int temp[]) { if(first<last) { int mid=(first+last)/2; mergesort(a,first,mid,temp); mergesort(a,mid+1,last,temp); merge(a,first,mid,last,temp); } } bool Mergesort(int a[],int n) { int *p=new int[n]; if(p==NULL) return false; mergesort(a,0,n-1,p); delete[] p; return 1; } int main() { int n; int a[200]; cin>>n; for(int i=0;i<n;i++) { cin>>a[i]; } Mergesort(a,n); for(int i=0;i<n;i++) { cout<<a[i]<<" "; } return 0; }
求逆序對?
answer:
比如將下面兩個區間排序
\qquad a_iai \quad mid=4mid=4 \quad a_jaj
\quad 3\,4\,7\,93479 \qquad \qquad 1\,5\,8\,1015810
首先將右區間的 11 取出,放到r_krk中,此時 11 是比每個a_iai中的元素都小,也就是說此時i的指標指向a_1a1的位置,此刻得到的逆序對的數量為 44 ; r_k= 1rk=1 ;
然後再將a_iai和a_jaj比較(直到a_i<a_jai<aj),a_i<a_jai<aj 將a_iai的元素放到r_krk中; r_k= 1\,3\,4rk=134;
現在a_j>a_iaj>ai, ii 指向a_3a3的位置,將 55 放到r_krk中,得到的逆序對數量為 22 ; r_k= 1\,3\,4\,5rk=1345
以此類推,直到進行完歸併排序,每次合併都會求出逆序對的數目,即mid-i+1mid−i+1,最後每次將ansans加上mid-i+1mid−i+1即可得到最後的答案;
#include<bits/stdc++.h> using namespace std; const int maxn=1008611; int a[maxn],temp[maxn]; int n; long long ans=0; void msort(int l,int r) { if(l==r) return ; int mid=(l+r)/2; int m=mid,n=r; msort(l,mid); msort(mid+1,r); int i=l,j=mid+1,k=0; while(i<=m&&j<=n) { if(a[i]<a[j]) temp[k++]=a[i++]; else { temp[k++]=a[j++]; ans+=mid-i+1; } } while(i<=m) temp[k++]=a[i++]; while(j<=n) temp[k++]=a[j++]; for(i=0;i<k;i++) { a[l+i]=temp[i]; } } int main() { scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d",&a[i]); } msort(0,n-1); printf("%lld\n",ans); return 0; }