• 怀念一下归并+逆序对


    /*
    codevs 4163 神犇与逆序对 
    */
    #include<cstdio>
    #define ll long long
    #define maxn 1000010
    using namespace std;
    ll n,a[maxn],b[maxn],ans;
    ll init()
    {
        ll x=0;char s;s=getchar();
        while(s<'0'||s>'9')s=getchar();
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x;
    }
    void Merge_sort(ll l,ll r)
    {
        if(l==r)return ;
        ll mid=(l+r)/2;
        Merge_sort(l,mid);
        Merge_sort(mid+1,r);
        ll i=l,j=mid+1,k=l;
        while(i<=mid&&j<=r)
          {
              if(a[i]>a[j])
                {
                    b[k++]=a[j++];ans+=mid-i+1;
              }
            else b[k++]=a[i++];
          }
        while(i<=mid)b[k++]=a[i++];
        while(j<=r)b[k++]=a[j++];
        for(ll i=l;i<=r;i++)a[i]=b[i];
    }
    int main()
    {
        n=init();
        for(ll i=1;i<=n;i++)
          a[i]=init();
        Merge_sort(1,n);
        printf("%lld
    ",ans);
        return 0;
    }/*

    /*
    codevs 3286 火柴排队 
    首先要知道两点 1:两列火柴高度排名大小相同时排列答案最优 2:移动两个序
    
    列和移动一个序列步数一样
    证明嘛 自己想吧 ^ ^ 假设我们只移动第二个序列 消耗步数就是求下逆序对
    现在的问题就是求出第二个序列需要怎么移动
    求逆序对我们想到用归并排序 那么移动的目标就是有序序列1-n
    怎么和“两列火柴高度排名大小相同”联系起来呢
    这样 我们维护a1 a2 p1 p2几个序列
    a1[i]=j:原序列1中i位置处的高度排名 a2同理
    p1[i]=j:原序列1中高度排名i的位置 
    那p1[a2[i]]就是原序列2中i位置处的高度排名那么大的在1中的位置
    我们把这个位置记在p2[i]中 那就是需要把i移动到p2[i] 也就是逆序对的个数
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define mod 99999997
    #define maxn 2000020
    using namespace std;
    int n,a1[maxn],a2[maxn],p[maxn],l[maxn],w[maxn];
    long long ans;
    struct node
    {
        int o,h;
    }s1[maxn],s2[maxn];
    int init()
    {
        int x=0;char s;s=getchar();
        while(s<'0'||s>'9')s=getchar();
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x;
    }
    int cmp(const node &x,const node &y)
    {
        return x.h<y.h;
    }
    void Merge(int l,int r)
    {
        if(l==r)return ;
        int mid=(l+r)/2;
        Merge(l,mid);
        Merge(mid+1,r);
        int i=l,j=mid+1,k=l;
        while(i<=mid&&j<=r)
          {
              if(p[i]>p[j])
                {
                    w[k++]=p[j++];ans=(ans+mid-i+1)%mod;
              }
            else w[k++]=p[i++];
          }
        while(i<=mid)w[k++]=p[i++];
        while(j<=r)w[k++]=p[j++];
        for(int i=l;i<=r;i++)p[i]=w[i];
    }
    int main()
    {
        n=init();
        for(int i=1;i<=n;i++)
          {
              s1[i].h=init();
              s1[i].o=i;
          }
        for(int i=1;i<=n;i++)
          {
              s2[i].h=init();
              s2[i].o=i;
          }
        sort(s1+1,s1+1+n,cmp);
        sort(s2+1,s2+1+n,cmp);
        for(int i=1;i<=n;i++)
          {
              a1[s1[i].o]=i;
              a2[s2[i].o]=i;
          }
        for(int i=1;i<=n;i++)
          l[a1[i]]=i;
        for(int i=1;i<=n;i++)
          p[i]=l[a2[i]];
        Merge(1,n);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    tftp服务、串口工具minicom
    意外的“黄金点”
    软件工程实践总结
    关于 K米 —— 的案例分析
    关于git的学习
    第二次作业_需求分析与原型设计
    安装appium
    淘宝
    Selenium API基础 8种定位
    selenium
  • 原文地址:https://www.cnblogs.com/yanlifneg/p/5533845.html
Copyright © 2020-2023  润新知