Evanyou Blog 彩带

P3157 [CQOI2011]动态逆序对

题目描述

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

输入输出格式

输入格式:

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

输出格式:

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

输入输出样例

输入样例#1: 
5 4
1
5
3
4
2
5
1
4
2
输出样例#1: 
5
2
2
1

样例解释
(1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。

说明

N<=100000 M<=50000

 

Solution:

  本题带修改主席树板子。

  离散都不需要,直接对每个位置构建主席树,先求出逆序对个数,然后每次删数直接树状数组套主席树改下,考虑该数被删去后对逆序对个数的影响,无非就是排在它前面比它大的数的个数+排在它后面比它小的数的个数(提醒我们还得记录每个数在原序列出现的位置),原逆序对数剪掉这个值就好了。

  (注意:本题卡内存,我们发现每次主席树上的修改只与修改前的那棵主席树有关,而我们查询只需要当前最新的这棵主席树,并不需要返回到更之前的树的情况,所以我们可以回收内存,每次修改直接覆盖掉上棵树的节点就好了。)

代码:

/*Code by 520 -- 9.19*/
#include<bits/stdc++.h>
#define il inline
#define ll long long
#define RE register
#define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
#define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
#define lowbit(x) (x&-x)
using namespace std;
const int N=100005;
int n,m,a[N],rt[N],cnt,pos[N],X[N],Y[N],tx,ty;
struct node{
    int ls,rs,siz;
}t[N*120];
struct bit{
    int c[N];
    il void Clr(){memset(c,0,sizeof(c));}
    il void update(int x,int k){while(x<=n)c[x]+=k,x+=lowbit(x);}
    il int query(int x){int ans=0;while(x)ans+=c[x],x-=lowbit(x);return ans;}
}b;

int gi(){
    int a=0;char x=getchar();
    while(x<'0'||x>'9') x=getchar();
    while(x>='0'&&x<='9') a=(a<<3)+(a<<1)+(x^48),x=getchar();
    return a;
}

void ins(int l,int r,int k,int x,int lst,int &rt){
    if(!rt)rt=++cnt;t[rt].siz+=x;
    if(l==r) return;
    int m=l+r>>1;
    if(k<=m) ins(l,m,k,x,t[lst].ls,t[rt].ls);
    else ins(m+1,r,k,x,t[lst].rs,t[rt].rs);
}

il void update(int x,int v){
    int k=a[x];
    while(x<=n) ins(1,n,k,v,rt[x],rt[x]),x+=lowbit(x);
}

il int querysuc(int x,int y,int v){
    int l=1,r=n,ans=0;tx=0,ty=0;
    for(RE int i=x;i;i-=lowbit(i)) X[++tx]=rt[i];
    for(RE int i=y;i;i-=lowbit(i)) Y[++ty]=rt[i];
    while(l<r){
        int m=l+r>>1;
        if(m>=v){
            For(i,1,tx) X[i]=t[X[i]].ls;
            For(i,1,ty) Y[i]=t[Y[i]].ls;
            r=m;
        }
        else {
            For(i,1,tx) ans-=t[t[X[i]].ls].siz,X[i]=t[X[i]].rs;
            For(i,1,ty) ans+=t[t[Y[i]].ls].siz,Y[i]=t[Y[i]].rs;
            l=m+1;
        }
    }
    return ans;
}

il int querypre(int x,int y,int v){
    int l=1,r=n,ans=0;tx=0,ty=0;
    for(RE int i=x;i;i-=lowbit(i)) X[++tx]=rt[i];
    for(RE int i=y;i;i-=lowbit(i)) Y[++ty]=rt[i];
    while(l<r){
        int m=l+r>>1;
        if(m<v){
            For(i,1,tx) X[i]=t[X[i]].rs;
            For(i,1,ty) Y[i]=t[Y[i]].rs;
            l=m+1;
        }
        else {
            For(i,1,tx) ans-=t[t[X[i]].rs].siz,X[i]=t[X[i]].ls;
            For(i,1,ty) ans+=t[t[Y[i]].rs].siz,Y[i]=t[Y[i]].ls;
            r=m;
        }
    }
    return ans;
}

int main(){
    n=gi(),m=gi();b.Clr();
    int x;ll ans=0;
    memset(&t[0],0,sizeof(t[0]));
    For(i,1,n) {
        a[i]=gi(),pos[a[i]]=i,update(i,1);
        ans+=b.query(n)-b.query(a[i]);
        b.update(a[i],1);
    }
    For(i,1,m){
        x=pos[gi()];
        printf("%lld\n",ans);
        update(x,-1);
        ans-=querysuc(x,n,a[x])+querypre(0,x-1,a[x]);
    }
    return 0;
}

 

posted @ 2018-09-22 14:38  five20  阅读(177)  评论(0编辑  收藏  举报
Live2D