bzoj3223
Posted 宣毅鸣
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3223相关的知识,希望对你有一定的参考价值。
题解:
将当前排名为l-1 +1 的节点转到根
将当前排名为r+2的节点转到根的右子树的根节点
则根的右子树的根节点的左子树为所求区间
直接打标记就可以了
代码:
#include<bits/stdc++.h> using namespace std; const int N=100005; int n,m,sz,rt,pre[N],l,r,c[N][2],data[N],size[N],rev[N]; void pushup(int k) { size[k]=size[c[k][0]]+size[c[k][1]]+1; } void pushdown(int k) { int l=c[k][0],r=c[k][1]; if(rev[k]) { swap(c[k][0],c[k][1]); rev[l]^=1;rev[r]^=1; rev[k]=0; } } void rotate(int x,int &k) { int y=pre[x],z=pre[y],l,r; if(c[y][0]==x)l=0; else l=1; r=l^1; if(y==k)k=x; else {if(c[z][0]==y)c[z][0]=x;else c[z][1]=x;} pre[x]=z;pre[y]=x;pre[c[x][r]]=y; c[y][l]=c[x][r];c[x][r]=y; pushup(y);pushup(x); } void splay(int x,int &k) { while(x!=k) { int y=pre[x],z=pre[y]; if(y!=k) { if(c[y][0]==x^c[z][0]==y)rotate(x,k); else rotate(y,k); } rotate(x,k); } } int find(int k,int rank) { pushdown(k); int l=c[k][0],r=c[k][1]; if (size[l]+1==rank)return k; else if (size[l]>=rank)return find(l,rank); else return find(r,rank-size[l]-1); } void change(int l,int r) { int x=find(rt,l),y=find(rt,r+2); splay(x,rt);splay(y,c[x][1]); int z=c[y][0]; rev[z]^=1; } void build(int l,int r,int f) { if(l>r)return; int now=data[l],last=data[f]; if(l==r) { pre[now]=last;size[now]=1; if(l<f)c[last][0]=now; else c[last][1]=now; return; } int mid=(l+r)>>1;now=data[mid]; build(l,mid-1,mid); build(mid+1,r,mid); pre[now]=last;pushup(mid); if(mid<f)c[last][0]=now; else c[last][1]=now; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n+2;i++)data[i]=++sz; build(1,n+2,0);rt=(n+3)>>1; for(int i=1;i<=m;i++) { scanf("%d%d",&l,&r); change(l,r); } for(int i=2;i<=n+1;i++)printf("%d ",find(rt,i)-1); return 0; }
以上是关于bzoj3223的主要内容,如果未能解决你的问题,请参考以下文章