归并排序
1.归并排序
https://www.acwing.com/problem/content/789/
解题思路:
归并排序,以中间为线左右两遍进行排序,需借助外加数组。
递归到最底层,一层一层往上排序
#include<iostream>
using namespace std;
const int N = 1e5+10;
int n,a[N],b[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);//先递归至最底层(即j=i-1 j与i相连)
int i=l,j=mid+1;
int k=0;
//借助b数组进行排序
while(i<=mid&&j<=r){
if(a[i]<=a[j]) b[k++]=a[i++];
else b[k++]=a[j++];
}
while(i<=mid) b[k++]=a[i++];
while(j<=r) b[k++]=a[j++];
//把此部分排好序的b数组赋值给a数组
for(i=l,j=0;i<=r;i++,j++){
a[i]=b[j];
}
}
int main(){
cin>>n;
for(int i=0;i<n;++i) cin>>a[i];
merge_sort(0,n-1);
for(int i=0;i<n;++i) cout<<a[i]<<" ";
return 0;
}
2.逆序对的数目
https://www.acwing.com/problem/content/790/
解题思路
递归至最底层进行计算,一层一层相加
归并排序左右两遍皆是排序成从小到大的顺序,只需计算左边数大于右边数的个数
#include<iostream>
using namespace std;
const int N = 1e5+10;
int a[N],b[N],n;
long long merge_sort_def(int l,int r){
if(l>=r) return 0;
int mid = l+r>>1;
//每一层求得的数值都相加起来
long long res = merge_sort_def(l,mid)+merge_sort_def(mid+1,r);
int i=l,j=mid+1;
int k=0;
while(i<=mid&&j<=r){
if(a[i]>a[j]){
//符合条件
//左右两遍皆是有序,如果左边一个数会大于右边某个数,
//那么这个数的右边(以中间mid为界)所有的数都大于右边这个数
//计算出这个数到mid之间有多少数会大于右边这个数
res += mid - i + 1;
b[k++]=a[j++];
}else{
b[k++]=a[i++];
}
}
//归并模板进行排序
while(i<=mid) b[k++]=a[i++];
while(j<=r) b[k++]=a[j++];
for(i=l,j=0;i<=r;++i,++j) {
a[i]=b[j];
}
return res;
}
int main(){
cin>>n;
for(int i=0;i<n;++i) cin>>a[i];
cout<<merge_sort_def(0,n-1);
return 0;
}