• 还是火柴排队(补一下归并排序的锅)


    原文章传送门

    好吧,我们上次说这道题可以用归并排序做。。

    但是我不会归并排序的锅(真是蒟蒻。。)

    早晨爬起来赶紧学一发。。

    貌似还挺简单的。。

    233~

    好吧,切入正题。

    归并排序其实就是利用了分治的思想。

    分治:将一个大问题分为2个小问题,之后解决所有的小问题,再合并答案。

    比如我们举一个数列,对它进行归并排序。

    a[10]={9,2,3,5,4,6,6,7,9,5}

    归并的顺序是这样的

    {9,2,3,5,4}{6,6,7,9,5};

    {9,2,3}{5,4}{6,6,7}{9,5};

    {9,2}{3}{5,4}{6,6}{7}{9,5}

    分到这一步后,有2种方法:

    第一是继续分,然后归并,第二是不分,然后判断一下2个数的大小关系,如{9 2}变为{2 9}然后归并。。(其实复杂度差不多,就是少几个常数。。)

    合并过程:(接上表)

    {2,9}{3}{4 5}{6 6}{7}{5 9}

    {2,3,9}{4,5}{6,6,7}{5,9}

    {2,3,4,5,9}{5,6,6,7,9}

    {2,3,4,5,5,6,6,7,9,9}

    恩,就是这样。

    合并的代码实现就是将2块数组放2个指针。

    逐一扫描,比较。

    然后把结果重新放回原数组中

    好吧,感觉讲的不是很清楚。

    然后逆序对的个数呢,是这样的;

    在归并排序中

    假设我们要合并2个有序的数列a1,a2

    那么假设a1中left<=i<=mid 

    a2中mid<j<=right

    如果a1[i]>=a2[j]

    那么a1[k](i<=k<=mid)一定>a2[j]

    所以逆序对(也就是ans)+=mid-i+1;(+1是因为包括i本身也是逆序对)

    还是上代码吧。。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define mod 99999997
    using namespace std;
    struct lisan{
        int opt,value;
    }a[100001],b[100001];
    int result[100001],c[100001],d[100001],ans,n;
    bool cmp(lisan a,lisan b){ return a.value<b.value;}
    void mergesort(int left,int right){
        if(left>=right)return ;
        int mid=(left+right)>>1,i,j,k;    
        mergesort(left,mid);
        mergesort(mid+1,right);
        for(i=left,j=mid+1,k=left;i<=mid&&j<=right;k++)
        {
            if(c[i]<c[j])d[k]=c[i++];
            else ans+=mid-i+1,ans%=mod,d[k]=c[j++];
        }
        while(i<=mid)
        d[k++]=c[i++];
        while(j<=right)
        d[k++]=c[j++];
        for(i=left;i<=right;i++)
        c[i]=d[i];
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i].value);
            a[i].opt=i;
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&b[i].value);
            b[i].opt=i;
        }
        sort(a+1,a+n+1,cmp);
        sort(b+1,b+n+1,cmp);
        for(int i=1;i<=n;i++)
        c[b[i].opt]=a[i].opt;
        mergesort(1,n);
        printf("%d",ans);
    }

    比树状数组快诶。(树状数组背锅。。)

    其实都是O(nlogn)只不过常数小了点。

    恩,就是这样。

    线段树算法和乱七八糟的算法还是去死吧。。(等我成为蒟蒻中的巨神再回来补。。)

  • 相关阅读:
    电脑设置开机
    python 环境搭建 python-3.4.4
    遍历hashmap 的四种方法
    Java8 使用 stream().map()提取List对象的某一列值及排重
    解决 SpringMVC 非spring管理的工具类使用@Autowired注解注入DAO为null的问题
    CXF之"@XmlType.name 和 @XmlType.namespace 为类分配不同的名称"错误
    java.lang.NoSuchMethodError: javax.wsdl.xml.WSDLReader.readWSDL
    java.lang.IllegalArgumentException: URLDecoder: Illegal hex characters in escape (%) pattern
    java.lang.IllegalArgumentException: Request header is too large
    ie8 报错:意外地调用了方法或属性访问
  • 原文地址:https://www.cnblogs.com/ghostfly233/p/6848189.html
Copyright © 2020-2023  润新知