bzoj3295 [Cqoi2011]动态逆序对(cdq分治+树状数组)
2018-01-15 22:13
513 查看
我们把删除操作倒着考虑,变成逐渐加数,每个数按加入的顺序给时间标号ti。(没被删过的数随便按顺序给时间标号1…n-m),每个点我们记录三个信息(ti,xi,yi)分别表示时间标号,位置,数值,每一个点又都是一个询问,答案是加入这个点后增加的逆序对数。那么对于一个询问(t,x,y),他的答案就是满足
ti< t&&xi< x&&yi>y或者ti< t&&xi>x &&yi< y的点的个数。因此我们就是要求三维偏序。先按时间t排好序,然后每次分治里按x排序,y用树状数组来维护。因为有两种偏序要统计,因此我们要做两遍。最后的答案我们要做个前缀和,然后倒序输出对应的m个即可。
ti< t&&xi< x&&yi>y或者ti< t&&xi>x &&yi< y的点的个数。因此我们就是要求三维偏序。先按时间t排好序,然后每次分治里按x排序,y用树状数组来维护。因为有两种偏序要统计,因此我们要做两遍。最后的答案我们要做个前缀和,然后倒序输出对应的m个即可。
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; #define ll long long #define inf 0x7fffffff #define N 100010 inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } int n,m,a ,pos ,c ; ll ans ; bool del ; struct event{ int x,y,t; }e ,e1 ,tmp ; inline void add(int x,int val){for(;x<=n;x+=x&-x) c[x]+=val;} inline int ask(int x){int res=0;for(;x;x-=x&-x) res+=c[x];return res;} inline void cdq(int l,int r){ if(l==r) return; int mid=l+r>>1;cdq(l,mid);cdq(mid+1,r); int p1=l,p2=mid+1,owo=l; while(owo<=r){//先统计i前面的数和i构成的逆序对 if(p2>r||p1<=mid&&e[p1].x<e[p2].x) add(e[p1].y,1),tmp[owo++]=e[p1++]; else ans[e[p2].t]+=ask(n)-ask(e[p2].y),tmp[owo++]=e[p2++]; }for(int i=l;i<=mid;++i) add(e[i].y,-1); memcpy(e+l,tmp+l,sizeof(e[0])*(r-l+1)); p1=l;p2=mid+1;owo=l; while(owo<=r){//倒着插入,统计i后面的数和i构成的逆序对 if(p2>r||p1<=mid&&e1[p1].x>e1[p2].x) add(e1[p1].y,1),tmp[owo++]=e1[p1++]; else ans[e1[p2].t]+=ask(e1[p2].y-1),tmp[owo++]=e1[p2++]; }for(int i=l;i<=mid;++i) add(e1[i].y,-1); memcpy(e1+l,tmp+l,sizeof(e1[0])*(r-l+1)); } int main(){ // freopen("a.in","r",stdin); n=read();m=read();int tot=n; for(int i=1;i<=n;++i) a[i]=read(),pos[a[i]]=i; for(int i=1;i<=m;++i){ int x=read();e[tot].t=tot;e[tot].x=pos[x];e[tot].y=x; --tot;del[x]=1; }for(int i=1;i<=n;++i){ if(del[a[i]]) continue; e[tot].t=tot;e[tot].x=i;e[tot].y=a[i];--tot; }memcpy(e1,e,sizeof(e1));cdq(1,n); for(int i=2;i<=n;++i) ans[i]+=ans[i-1]; for(int i=n,cnt=1;cnt<=m;--i,++cnt) printf("%lld\n",ans[i]); return 0; }
相关文章推荐
- bzoj 3295: [Cqoi2011]动态逆序对 (CDQ分治+树状数组)
- BZOJ 3295 [CQOI2011] 动态逆序对
- [BZOJ3295][Cqoi2011]动态逆序对(分块重建)
- bzoj3295 [Cqoi2011]动态逆序对(CDQ分治)
- 【BZOJ3295】动态逆序对(CQOI2011)-CDQ分治:三维偏序
- bzoj 3295: [Cqoi2011]动态逆序对(树套树 or CDQ分治)
- bzoj 3295: [Cqoi2011]动态逆序对(树套树)
- BZOJ3295:[Cqoi2011]动态逆序对 (BIT套treap/CDQ分治+BIT)
- BZOJ 3295: [Cqoi2011]动态逆序对 分块大法好
- [BZOJ3295][Cqoi2011]动态逆序对(CDQ分治||树套树)
- [BZOJ3295][Cqoi2011]动态逆序对(树状数组套线段树||cdq分治)
- bzoj 3295 [Cqoi2011]动态逆序对(cdq分治,BIT)
- 【BZOJ】【3295】【CQOI2011】动态逆序对
- BZOJ 3295: [Cqoi2011]动态逆序对 (树状数组套主席树)
- [bzoj3295][Cqoi2011][动态逆序对] (树套树)
- [BZOJ3295][CQOI2011]动态逆序对-CDQ分治+树状数组
- bzoj3295[Cqoi2011]动态逆序对(cdq分治||可持久化线段树)
- BZOJ 3295 [Cqoi2011]动态逆序对 - 树状数组套主席树/树状数组套treap
- [BZOJ3295] [Cqoi2011]动态逆序对 (树套树)or(CDQ分治)
- bzoj 3295: [Cqoi2011]动态逆序对 cdq分治+树状数组