洛谷【模板】文艺平衡树
主要新操作是区间翻转,转一个区间[l,r],需要把l-1转到根,把r+1转到l-1(现在的根)的左儿子,使[l,r]独立出来成为r+1的子树
这样便可以操作了(子树上每个节点都交换左右儿子(想一想)),优化的话打个lazy就是了
#include<iostream> #include<cstdlib> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<map> #define rg register #define _ (int)1e5+5 using namespace std; int n,m,num,root; struct pp { int son[2],dad,cnt,it,size; bool lazy; }tr[_]; inline int read() { rg int save=0,w=1;rg char q=getchar(); while(q<'0'||q>'9'){if(q=='-')w=-1;q=getchar();} while(q>='0'&&q<='9')save=(save<<3)+(save<<1)+q-'0',q=getchar(); return save*w; } inline void pushup(rg int x) { tr[x].size=tr[tr[x].son[0]].size+tr[tr[x].son[1]].size+tr[x].cnt; }/* inline void doit(rg int x) { rg int y=tr[x].dad,z=tr[y].dad; rg bool k=tr[y].son[1]==x; tr[x].dad=z; tr[z].son[tr[z].son[1]==y]=x; tr[y].son[k]=tr[x].son[!k]; tr[tr[y].son[k]].dad=y; tr[y].dad=x; tr[x].son[!k]=y; pushup(y),pushup(x);//记住要更新size!!! }*/ inline void doit(rg int x)//一个结点的旋转 { rg int y=tr[x].dad,z=tr[y].dad; rg bool k=tr[y].son[1]==x; tr[x].dad=z; tr[z].son[tr[z].son[1]==y]=x; tr[y].son[k]=tr[x].son[!k]; tr[tr[y].son[k]].dad=y; tr[y].dad=x; tr[x].son[!k]=y; pushup(y),pushup(x);//记住要更新size!!! } inline void splay(rg int x,rg int to)//x是坐标 { while(tr[x].dad!=to) { rg int y=tr[x].dad,z=tr[y].dad; if(z!=to) (tr[z].son[1]==y)^(tr[y].son[1]==x)?doit(x):doit(y); doit(x); } if(!to)root=x; } inline void insert(rg int x)//x是值 { rg int now=root,fa=0; while(now&&tr[now].it!=x) fa=now,now=tr[now].son[x>tr[now].it]; if(!now) { now=++num; tr[now].it=x,tr[now].cnt=1; tr[now].size=1; tr[now].dad=fa; tr[now].son[0]=tr[now].son[1]=0; if(fa)tr[fa].son[x>tr[fa].it]=now; } else tr[now].cnt++; splay(now,0); } inline void down(rg int x)//x是坐标 { rg int l=tr[x].son[0],r=tr[x].son[1]; tr[l].lazy^=1,tr[r].lazy^=1; tr[x].lazy=0; tr[x].son[1]=l,tr[x].son[0]=r; // swap(l,r); } inline int Kth(rg int x)//第x个 { rg int now=root; if(x>tr[root].size)return 0; while(2233) { if(tr[now].lazy)down(now); rg int front=tr[tr[now].son[0]].size+tr[now].cnt; if(x<=tr[tr[now].son[0]].size)now=tr[now].son[0]; else if(x>front)now=tr[now].son[1],x-=front; else return now; } } inline void solve(rg int l,rg int r)//把l-1转到根,把r+1转到根的右节点,[l,r]就被放在同一颗子树里了 { rg int ll=Kth(l),rr=Kth(r+2); splay(ll,0);splay(rr,ll); tr[tr[rr/*tr[root].son[1]*/].son[0]].lazy^=1; } void putout(rg int now) { if(tr[now].lazy) down(now); if(tr[now].son[0])putout(tr[now].son[0]); if(tr[now].it!=-2147483647&&tr[now].it!=2147483647)printf("%d ",tr[now].it); if(tr[now].son[1])putout(tr[now].son[1]); } int main() { n=read(),m=read(); insert(-2147483647),insert(2147483647); rg int i,j; for(i=1;i<=n;++i)insert(i); for(i=1;i<=m;++i) { rg int l=read(),r=read(); solve(l,r); } putout(root); puts(""); return 0; }