归并排序
流程:
代码实现($O(n\log n)$)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #include<bits/stdc++.h> using namespace std;
const int N=1e6+5; int n; int q[N];
void merge_sort(int l,int r){ if(l>=r)return; int mid=l+r>>1; merge_sort(l,mid),merge_sort(mid+1,r); int tmp[N],cnta=l,cntb=mid+1; for(int i=l;i<=r;i++){ if(cnta==mid+1){ tmp[i]=q[cntb++]; } else if(cntb==r+1){ tmp[i]=q[cnta++]; } else{ if(q[cnta]<q[cntb]){ tmp[i]=q[cnta++]; } else{ tmp[i]=q[cntb++]; } } } for(int i=l;i<=r;i++){ q[i]=tmp[i]; } }
int main(){ cin >> n; for(int i=1;i<=n;i++){ cin >> q[i]; } merge_sort(1,n); for(int i=1;i<=n;i++){ cout << q[i] << ' '; } return 0; }
|
应用
逆序对:若有一对数$a_i$,$a_j$($i<j$)且$a_i>a_j$,则这对数是一个逆序对
方法:
归并排序
每次合并时,当取到$q[cntb]$时($q[cntb]>q[cnta]$),此时,对于所有$q[cnta\thicksim mid]$都小于$q[cntb]$,且所有的$q[cnta\thicksim mid]$在原数组中都位于$q[cntb]$的左侧,所以都是逆序对,共$mid-cnta+1$对
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| #include<bits/stdc++.h> using namespace std;
const int N=1e6+5; int n; int q[N]; long long ans; void merge_sort(int l,int r){ if(l>=r)return; int mid=l+r>>1; merge_sort(l,mid),merge_sort(mid+1,r); int tmp[N],cnta=l,cntb=mid+1; for(int i=l;i<=r;i++){ if(cnta==mid+1){ tmp[i]=q[cntb++]; ans+=mid-cnta+1; } else if(cntb==r+1){ tmp[i]=q[cnta++]; } else{ if(q[cnta]<=q[cntb]){ tmp[i]=q[cnta++]; } else{ tmp[i]=q[cntb++]; ans+=mid-cnta+1; } } } for(int i=l;i<=r;i++){ q[i]=tmp[i]; } }
int main(){ cin >> n; for(int i=1;i<=n;i++){ cin >> q[i]; } merge_sort(1,n); cout << ans << endl; return 0; }
|