• 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
    */
    
  • 相关阅读:
    Matlab之快速傅里叶变换
    关于Debug和Release的区别 (VS C#)
    QSqlQuery::value: not positioned on a valid record
    UML系列图--用例图
    SQLite 数据类型总结
    c++构造函数
    求Fibonacci数列通项公式
    ObjectMapper类
    命令行运行jar 提示找不到主程序解决方案
    httpclient框架实现接口自动化的思路(二)
  • 原文地址:https://www.cnblogs.com/gryzy/p/15539593.html
Copyright © 2020-2023  润新知