• bzoj3295: [Cqoi2011]动态逆序对


    3295: [Cqoi2011]动态逆序对

    Description

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

    Input

    输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数。

    以下n行每行包含一个1到n之间的正整数,即初始排列。

    以下m行每行一个正整数,依次为每次删除的元素。

    Output

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

    数据范围

    $N \leqslant 100000 , M \leqslant50000 $

    这道题将插入时间转化为一维,就是个三维偏序,直接cdq即可。

    注意输入的是元素大小,而不是元素个数。

    #include<bits/stdc++.h>
    using namespace std;
    #define REP(i,st,ed) for(register int i=st,i##end=ed;i<=i##end;++i)
    #define DREP(i,st,ed) for(register int i=st,i##end=ed;i>=i##end;--i)
    typedef long long ll;
    inline int read(){
        int x;
        char c;
        int f=1;
        while((c=getchar())!='-' && (c<'0' || c>'9'));
        if(c=='-') c=getchar(),f=-1;
        x=c^'0';
        while((c=getchar())>='0' && c<='9') x=(x<<1)+(x<<3)+(c^'0');
        return x*f;
    }
    inline ll readll(){
        ll x;
        char c;
        ll f=1;
        while((c=getchar())!='-' && (c<'0' || c>'9'));
        if(c=='-') c=getchar(),f=-1;
        x=c^'0';
        while((c=getchar())>='0' && c<='9') x=(x<<1ll)+(x<<3ll)+(c^'0');
        return x*f;
    }
    inline bool chkmax(int &x,int y){return (y>x)?(x=y,1):0;}
    inline bool chkmin(int &x,int y){return (y<x)?(x=y,1):0;}
    const int maxn=1e5+10;
    struct point{
        int x,y,z,sum;
    }a[maxn];
    bool cmpx(const point A,const point B){
        if(A.x!=B.x) return A.x<B.x;
        if(A.y!=B.y) return A.y<B.y;
        return A.z<B.z;
    }
    bool cmpy(const point A,const point B){
        if(A.y!=B.y) return A.y<B.y;
        return A.z<B.z;
    }
    int n;
    ll ans[maxn];
    struct szsz{
        int c[maxn];
        int lowbit(int x){
            return x&(-x);
        }
        int sum(int x){
            int res=0;
            while(x){
                res+=c[x];
                x-=lowbit(x);
            }
            return res;
        }
        void add(int x,int y){
            while(x<=n){
                c[x]+=y;
                x+=lowbit(x);
            }
        }
    }bit;
    void cdq(int L,int R){
        if(L>=R) return;
        int Mid=(L+R)>>1;
        cdq(L,Mid),cdq(Mid+1,R);
        sort(a+L,a+Mid+1,cmpy),sort(a+Mid+1,a+R+1,cmpy);
        int j=L;
        for(int i=Mid+1;i<=R;++i){
            while(j<=Mid && a[j].y<=a[i].y) bit.add(a[j].z,1),++j;
            a[i].sum+=bit.sum(n)-bit.sum(a[i].z);
        }
        REP(i,L,j-1) bit.add(a[i].z,-1);
        j=Mid;
        for(int i=R;i>Mid;--i){
            while(j>=L && a[j].y>=a[i].y) bit.add(a[j].z,1),--j;
            a[i].sum+=bit.sum(a[i].z);
        }
        DREP(i,Mid,j+1) bit.add(a[i].z,-1);
    }
    int mp[maxn];
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("cdq.in","r",stdin);
        freopen("cdq.out","w",stdout);
    #endif
        n=read();int m=read();
        REP(i,1,n) a[i].x=0,a[i].y=i,a[i].z=read(),mp[a[i].z]=i;
        int num=n;
        REP(i,1,m){
            int x=read();x=mp[x];
            a[x].x=num--;
        }
        REP(i,1,m) if(a[i].x==0) a[i].x=num--;
        sort(a+1,a+n+1,cmpx);
        cdq(1,n);
        REP(i,1,n) ans[a[i].x]+=a[i].sum;
        REP(i,1,n) ans[i]+=ans[i-1];
        DREP(i,n,n-m+1) printf("%lld\n",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    我们都可以把它放 Sidecar 容器中,这样微服务具备了 Super power,一种超能力
    DP 状态 DP 转移方程 动态规划解题思路
    完全二叉树 原因 完全二叉树最后一层节点靠左的原因
    延时任务最佳实践方案总结
    b+ 树 只存储 索引
    埋点质量保障体系建设
    linux命令重定向>、>>、 1>、 2>、 1>>、 2>>、 <
    卡特兰数
    python 使用函数名的字符串调用函数(4种方法)_black-heart的专栏-CSDN博客 https://blog.csdn.net/mrqingyu/article/details/84403924
    12 | 服务注册与发现如何满足服务治理
  • 原文地址:https://www.cnblogs.com/zhou888/p/8511904.html
Copyright © 2020-2023  润新知