归并排序 Mergesort

来源:互联网 发布:程序员用外星人 编辑:程序博客网 时间:2024/04/25 08:01

这玩意就是个裸的分治+twopointer,这样每次处理的都是n/2^p 总共处理logn段,共nlogn

感谢Flere825提供的思路

填坑:首先我们根据归并排序可知 假如产生了逆序对数 则L[i]>R[j]

这样就产生了L部分剩余元素个逆序对数

同时在原本的归并排序我们使用两个哨兵来记录堆是否为空

但是我们发现这并没有必要 我们只需要维护左数组的指针和右数组的指针 直到mid和len即可

建议练习题:POJ2299

封坑

#include<cstdio>#include<cstdlib>#include<iostream>#include<algorithm>#include<cmath>#include<cstring>#include<queue>#define INF 0X7f7f7f7fusing namespace std;int num[300001];int temp[300001];int n;long long mergesort(int l,int r,int mid,int now[]){long long ans=0;    int i=l;int j=mid+1;    int cnt=0;    while(i<=mid&&j<=r)    {        if(now[i]<=now[j]){ temp[++cnt]=now[i++];}        else {temp[++cnt]=now[j++];ans+=(mid-i+1);}        //放入temp临时数组内,不需要清空     }    while(i<=mid)    {        temp[++cnt]=now[i++];    }    while(j<=r)    {        temp[++cnt]=now[j++];    }    for(int i=1;i<=cnt;i++)    {        now[l+i-1]=temp[i];    }    return ans;}long long solve(int l,int r,int now[]){    long long tot;    tot=0;    if(l<r)    {        int mid=(l+r)>>1;        tot+=solve(l,mid,now);        tot+=solve(mid+1,r,now);        tot+=mergesort(l,r,mid,now);    }    return tot;}int main(){     cin>>n;    for(int i=1;i<=n;i++)    {        scanf("%d",&num[i]);    }    long long ans=solve(1,n,num);    cout<<ans<<endl;return 0; }//5 7 0 1 2 3 ////4

0 0
原创粉丝点击