归并排序(模板题)

归并排序

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;
}

猜你喜欢

转载自blog.csdn.net/qq_44922497/article/details/113859668