zoukankan      html  css  js  c++  java
  • cogs1715 动态逆序对

    1715. [CQOI2011]动态逆序对

    输入文件:inverse.in 输出文件:inverse.out 简单对比
    时间限制:2 s 内存限制:128 MiB

    【题目描述】

    对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。

    【输入格式】

    输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数。以下n行每行包含一个1到n之间的正整数,即初始排列。以下m行每行一个正整数,依次为每次删除的元素。

    【输出格式】

    输出包含m行,依次为删除每个元素之前,逆序对的个数。

    【样例输入】

      5 4
      1
      5
      3
      4
      2
      5
      1
      4
      2
    

    【样例输出】

      5
      2
      2
      1
    

    样例解释

    (1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。

    【提示】

    N<=100000 M<=50000

    时间、位置、大小三维偏序
    每个数加入后,可能有两种方式构成逆序对,比自己位置靠前但数值小的,比自己位置靠后但数值大的。所以要写两次CDQ。求出的每个数加入后新产生的逆序对的数量。所以还要写一个前缀和。
    就这么个东西,写了一天多!水平太差!


    /*
        COGS1715:动态逆序对
    */
    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int maxn=1e5+10;
    const int maxm=5e4+10;
    int n,m;
    struct node
    {
        int pos,x,t;
        bool operator < (const node &a)const
        {
    //        if(t!=a.t)return t<a.t;
            if(pos!=a.pos)return pos<a.pos;
            return 0;
        }
    }sz[maxn],f[maxn];
    int ans[maxm],ansf[maxm];
    int tt[maxn];
    bool cmp(node a,node b)
    {
        if(a.t!=b.t)return a.t<b.t;
        if(a.pos!=b.pos)return  a.pos<b.pos;
    }
    bool cmpf(node a,node b)
    {
        if(a.t!=b.t)return a.t<b.t;
        if(a.pos!=b.pos)return  a.pos>b.pos;
    }
    int sm[maxn];
    void add(int sm[],int pos,int x)
    {
        for(int i=pos;i<=n;i+=i&-i)sm[i]+=x;
    }
    int query(int sm[],int pos)
    {
        int ret=0;
        for(int i=pos;i;i-=i&-i)ret+=sm[i];
        return ret;
    }
    void cdq(int l,int r)
    {
        if(l==r)return ;
        int mid=(l+r)>>1;
        cdq(l,mid);
        cdq(mid+1,r);
        int q=l,h=mid+1,p=l;
        while(q<=mid&&h<=r)
        {
            
            if(sz[q].pos<sz[h].pos)//sz[q]时间小,位置前
            {
                f[p]=sz[q];
                add(sm,sz[q].x,1);
                //add(smm,sz[q].x,1);
                //ans[sz[h].t]+=h-mid-query(smm,sz[h].x)-1;
                ++p;++q;
            }
            else//sz[q]时间小,位置后
            {
                f[p]=sz[h];
                ans[sz[h].t]+=q-l-query(sm,sz[h].x);
                ++p;++h;
            }
        }
        while(q<=mid)
        {
             f[p]=sz[q];
                add(sm,sz[q].x,1);
                //add(smm,sz[q].x,1);
                //ans[sz[h].t]+=h-mid-query(smm,sz[h].x)-1;
                ++p;++q;
        }    
        while(h<=r)
        {
            f[p]=sz[h];
                ans[sz[h].t]+=q-l-query(sm,sz[h].x);
                ++p;++h;
        }
        for(int i=l;i<=mid;++i)add(sm,sz[i].x,-1);
    //    for(int i=mid+1;i<=r;++i)add(smm,sz[i].x,-1);
        for(int i=l;i<=r;++i)sz[i]=f[i];
    }
    void cdqf(int l,int r)
    {
        if(l==r)return ;
        int mid=(l+r)>>1;
        cdqf(l,mid);
        cdqf(mid+1,r);
        int q=l,h=mid+1,p=l;
        while(q<=mid&&h<=r)
        {
            
            if(sz[q].pos>sz[h].pos)//sz[q]时间小,位置前
            {
                f[p]=sz[q];
                add(sm,sz[q].x,1);
                //add(smm,sz[q].x,1);
                //ans[sz[h].t]+=h-mid-query(smm,sz[h].x)-1;
                ++p;++q;
            }
            else//sz[q]时间小,位置后
            {
                f[p]=sz[h];
                ansf[sz[h].t]+=query(sm,sz[h].x);
                ++p;++h;
            }
        }
        while(q<=mid)
        {
             f[p]=sz[q];
                add(sm,sz[q].x,1);
                //add(smm,sz[q].x,1);
                //ans[sz[h].t]+=h-mid-query(smm,sz[h].x)-1;
                ++p;++q;
        }    
        while(h<=r)
        {
                f[p]=sz[h];
                ansf[sz[h].t]+=query(sm,sz[h].x);
                ++p;++h;
        }
        for(int i=l;i<=mid;++i)add(sm,sz[i].x,-1);
    //    for(int i=mid+1;i<=r;++i)add(smm,sz[i].x,-1);
        for(int i=l;i<=r;++i)sz[i]=f[i];
    }
    signed main()
    {
        freopen("inverse.in","r",stdin);
        freopen("inverse.out","w",stdout);
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;++i)
        {
            scanf("%lld",&sz[i].x);
            sz[i].pos=i;
        }
        for(int x,i=1;i<=m;++i)
        {
            scanf("%lld",&x);
            tt[x]=m-i+1;
        }
        for(int i=1;i<=n;++i)sz[i].t=tt[sz[i].x];
        sort(sz+1,sz+1+n,cmp);
        cdq(1,n);
        sort(sz+1,sz+1+n,cmpf);
        cdqf(1,n);
        ans[0]=0;
        for(int i=0;i<=m;++i)ans[i]+=ansf[i];
        for(int i=1;i<=m;++i)ans[i]+=ans[i-1];
     //   printf("%d\n",ans[0]+ansf[0]);
        for(int i=m;i>=1;--i)printf("%lld\n",ans[i]);
        return 0;
    }
    /*s
    3 2
    3 1 2
    3 1
    
    
    2
    2
    */
    
  • 相关阅读:
    datanode报错Problem connecting to server
    使用命令查看hdfs的状态
    Access denied for user root. Superuser privilege is requ
    ElasticSearch默认的分页参数 size
    SparkStreaming Kafka 维护offset
    【容错篇】Spark Streaming的还原药水——Checkpoint
    251 Android 线性与相对布局简介
    250 Android Studio使用指南 总结
    249 如何解决项目导入产生的中文乱码问题
    248 gradle更新问题
  • 原文地址:https://www.cnblogs.com/gryzy/p/15539593.html
Copyright © 2011-2022 走看看