zoukankan      html  css  js  c++  java
  • 归并排序

    运用了分治的思想,将一个数组分成几乎相等的两份,分别将两段中第一个最小的数拿出来放在一个临时数组中,直到全部取完。因为是递归的,所以每一段的数列都是排序好的。

    void merge_sort(ll *A,ll *B,int x,int y)
    {
        if(y-x<=1)return;
        int m=x+(y-x>>1);
        int p=x,q=m,i=x;
        merge_sort(A,B,x,m);
        merge_sort(A,B,m,y);
        while(p<m or q<y)
        {
            if(q>=y or (p<m and A[p]<=A[q]))B[i++]=A[p++];
            else B[i++]=A[q++];
        }
        for(int i=x;i<y;i++)A[i]=B[i];
    }

    (没验证,有错误请指出)

    这段代码中左端为闭,右端为开。因此调用时要将右端点+1

    O(nlogn)

    它有一个神奇的应用:求逆序对(的和)!因为我们发现每次递归时左边的还没有入列的数都是大于右边的数的,所以我们只要在else句的后面加上ans+=m-p就好辣!

    洛谷P1908

    #include<iostream>
    #include<cstdio>
    using namespace std;
    typedef long long ll;
    template <typename T>
    inline T read()
    {
        int w=0;T x=0;char c=getchar();
        while(!isdigit(c))w|=c=='-',c=getchar();
        while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
        return w?-x:x;
    }
    const int maxn=5e5+10;
    int n;
    ll A[maxn],B[maxn],ans;
    
    void merge_sort(ll *A,ll *B,int x,int y)
    {
        if(y-x<=1)return;
        int mid=x+(y-x)/2;
        int p=x,q=mid,i=x;
        merge_sort(A,B,x,mid);
        merge_sort(A,B,mid,y);
        while(p<mid or q<y)
        {
            if(q>=y or (p<mid and A[p]<=A[q]))B[i++]=A[p++];
            else B[i++]=A[q++],ans+=mid-p;
        }
        for(int i=x;i<y;i++)A[i]=B[i];
    }
    
    int main()
    {
        n=read<int>();
        for(int i=1;i<=n;i++)A[i]=read<ll>();
        merge_sort(A,B,1,n+1);
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    Boost练习程序(强制转换)
    4873279(1002)
    A+B Problem(1000)
    STL练习程序(去除相同元素)
    Boost练习程序(智能指针)
    Sql技巧总结
    MySql Show Status详解
    mysql show status调优
    mysql decimal、numeric数据类型
    Apache Thrift学习小记
  • 原文地址:https://www.cnblogs.com/BrotherHood/p/13330727.html
Copyright © 2011-2022 走看看