重拾归并排序

今天月考完,突然想到排序这个东西,一直用的都是STL的sort和简单的冒泡排序
归并排序…只记得一个大体思路,好像从来都没有代码实现过
所以心血来潮重新看了一下(:3_ヽ)_ 神tm这都高二下学期了


归并排序的思想就是分治,把整个数组从中间分开分成两个小数组,两个小数组排序,最后再合并成一个大数组,这样一直划分,直到划分出来了两个的长度均为1时,就可以开始向回合并了
合并的时候两个子数组间两两逐个比较即可(因为子数组已经是有序的了),并入原数组之后就将并入的元素在临时空间中删去,一直删到最后。
合并子数组时间复杂度是O(n),合并次数是O(log n)<典型的二分复杂度,底数当然是2>
总的时间复杂度就是他们的乘积O(n log n)啦
不得不说书上的代码实现等各方面真是胜我百倍。。。
归并排序的用处,主要应该是求逆序对吧。。。
譬如

洛谷的 P1908


下面是我的题解:
求逆序对,只需跑一边归并排序
每次归并排序的时候,如果是先加入了右半个子数组的元素,可知此时存在逆序对,逆序对的个数为左半个子数组剩下的元素的数目,答案加上这个数即可
代码如下

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define For(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
int a[100010],n,temp[100010],ans;
void merge(int l,int r)
{
    int l1=l,r1=(l+r)>>1,l2=((l+r)>>1)+1,r2=r,i=l;
    while(l1<=r1&&l2<=r2)
    {
        if(a[l1]<=a[l2])
         temp[i++]=a[l1++];
        else
        {
            temp[i++]=a[l2++];
            ans+=r1-l1+1;
        }
    }
    while(l1<=r1)
     temp[i++]=a[l1++];
    while(l2<=r2)
     temp[i++]=a[l2++];
    For(i,l,r)
     a[i]=temp[i];
}
void msort(int l,int r)
{
    if(l<r)
    {
        msort(l,(l+r)>>1);
        msort(((l+r)>>1)+1,r);
        merge(l,r);
    }
}
int main()
{
    cin>>n;
    For(i,1,n)
    cin>>a[i];
    msort(1,n);
    //For(i,1,n)
    // cout<<a[i]<<' ';
    cout<<ans;
    return 0;
}

快排模板题

洛谷P1177


也是可以直接用归并排序过的233


参考资料:https://blog.youkuaiyun.com/chencangui/article/details/44680113/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值