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; }
PS:~蒟蒻写博客不易,转载请注明出处,万分感谢!~