分治求逆序數(CDQ)
阿新 • • 發佈:2018-12-29
歸併排序 #include<bits/stdc++.h> using namespace std; int b[100]; void merge_sort(int l,int r,int *a){ if(l==r)return; int m=(l+r)>>1; merge_sort(l,m,a); merge_sort(m+1,r,a); int t1=l,t2=m+1; for(int i=l;i<=r;i++){ if((a[t1]<a[t2]&&t1<=m)||t2>r){ b[i]=a[t1++]; } else{ b[i]=a[t2++]; } } for(int i=l;i<=r;i++)a[i]=b[i]; } int main(){ int c[10]={5,6,87,8,45,7,2,1,14,3}; merge_sort(0,9,c); for(int i=0;i<10;i++)cout<<c[i]<<' '; }
CDQ分治求逆序數 #include<bits/stdc++.h> using namespace std; const int maxn=1e6+9; int a[maxn],b[maxn],ans=0; void CDQ(int l,int r,int *a){ if(l==r)return; int m=(l+r)>>1; CDQ(l,m,a); CDQ(m+1,r,a); int t1=l,t2=m+1; for(int i=l;i<=r;i++){ if(a[t1]>a[t2]&&t2<=r||t1>m){ b[i]=a[t2++]; ans+=m-t1+1;//關鍵程式碼 } else{ b[i]=a[t1++]; } } for(int i=l;i<=r;i++)a[i]=b[i]; } int main(){ int i,j,k,n; cin>>n; for(i=1;i<=n;i++){ cin>>a[i]; } CDQ(1,n,a); cout<<ans<<endl; } 關鍵程式碼解釋: 既然左區間和右區間有序,不妨設左區間為[1,k],右區間為[k+1,n],那麼若是a[i]>a[j](a[i]為左區間裡的一個數,a[j]為右區間的一個數),那麼ans+=k-i+1,我們對左區間裡的每一個數進行這樣一個比較,便能求得整個區間的逆序對數。 K+1-i是指,當前對於a[j],左區間比其大的數字的個數,剛好就是K+1-i個,因為區間長K,第i個開始比其大,顯然易得。