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;
}
posted @ 2018-03-05 23:01  zhou888  阅读(125)  评论(0编辑  收藏  举报