• BZOJ3295:[CQOI2011]动态逆序对——题解


    http://www.lydsy.com/JudgeOnline/problem.php?id=3295

    Description

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

    Input

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

    Output

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

    Sample Input

    5 4
    1
    5
    3
    4
    2
    5
    1
    4
    2

    Sample Output

    5
    2
    2
    1

    ——————————————————————————————

    这题不开longlong成功见祖宗……

    乍一看我们想不到CDQ,但是显然删除操作不好整,我们将删除变成插入,插入的时间点为t,插入的位置为p,插入的值为n。

    则三元组(t,p,n)它的逆序对需要满足t0<t,p0<p,n0>n或者t0<t,p0>p,n0<n

    这不就成三维偏序了吗?解完之后求一遍前缀和即是答案。

    #include<cstdio>
    #include<queue>
    #include<cctype>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=100001;
    inline int read(){
        int X=0,w=0; char ch=0;
        while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
        while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    struct del{
        int t;
        int p;
        int n;
    }q[N],tmp[N];
    ll m,n,ans[N],pos[N],tree[N];
    inline int lowbit(int t){return t&(-t);}
    void add(int x,int y){//将a[x]+y
        for(int i=x;i<=n;i+=lowbit(i))tree[i]+=y;
        return;
    }
    ll query(int x){//1-x区间和
        ll res=0;
        for(int i=x;i>0;i-=lowbit(i))res+=tree[i];
        return res;
    }
    void cdq(int l,int r){
        if(l>=r)return;
        int mid=(l+r)>>1;
        cdq(l,mid);cdq(mid+1,r);
        for(int i=l,j=l,p=mid+1;i<=r;i++){
        if(j<=mid&&(p>r||q[j].n>q[p].n))tmp[i]=q[j++];
        else tmp[i]=q[p++];
        }
        for(int i=l;i<=r;i++){
        q[i]=tmp[i];
        if(q[i].t<=mid)add(q[i].p,1);
        else ans[q[i].t]+=query(q[i].p);
        }
        for(int i=l;i<=r;i++)if(q[i].t<=mid)add(q[i].p,-1);
        for(int i=r;i>=l;i--){
        if(q[i].t<=mid)add(q[i].p,1);
        else ans[q[i].t]+=query(n)-query(q[i].p);
        }
        for(int i=l;i<=r;i++)if(q[i].t<=mid)add(q[i].p,-1);
        return;
    }
    bool vis[N];
    int main(){
        n=read();
        m=read();
        for(int i=1;i<=n;i++)pos[read()]=i;
        for(int i=n;i>=n-m+1;i--){
        q[i].t=i;
        q[i].n=read();
        q[i].p=pos[q[i].n];
        vis[q[i].n]=1;
        }
        int cnt=n-m;
        for(int i=1;i<=n;i++){
        if(!vis[i]){
            q[cnt].t=cnt;
            q[cnt].n=i;
            q[cnt--].p=pos[i];
        }
        }
        cdq(1,n);
        for(int i=1;i<=n;i++)ans[i]+=ans[i-1];
        for(int i=n;i>=n-m+1;i--)printf("%lld
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    移动零
    移除元素
    Ubuntu下安装PIL
    CSS颜色代码大全
    Test__GUI__用java编写一个简单的记事本程序,打包成jar双击运行
    Test__GUI__列出指定目录内容
    GUI__【GUI概述】【布局】【Frame】【事件监听机制】【窗体事件】【按钮】【鼠标事件】【键盘事件】【Dialog对话框】【菜单】
    Test__IO流综合应用的小练习
    IO流__【转换流的字符编码】【编码与解码】【字符编码-“联通”】
    IO流__【对象的序列化】【管道流】【RandomAccessFile】【DataStream】【ByteArrayStream等】
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8044201.html
Copyright © 2020-2023  润新知