题目大意:给定一个$1sim n$的序列,每次翻转一个区间,输出最后的序列。
解题思路:Splay的区间翻转操作。我借此打了个Splay的模板(运用内存池,但有些功能不确定正确,例如单点插入)。
大致思路就是,每次找到$l−1$和$r+1$两个节点,把$l−1$旋转到根,$r+1$旋转到根的右子树,则根的右子树的左子树就是$l,r$的区间。
对于翻转一个区间,直接打上标记,访问到这个节点时,下传标记并交换两个儿子节点。
注意访问$l−1$,$r+1$时可能访问到$0$和$n+1$,所以要多开两个节点。
最后输出即可。
C++ Code:
#include<bits/stdc++.h> inline int readint(){ char c=getchar(); for(;!isdigit(c);c=getchar()); int d=0; for(;isdigit(c);c=getchar()) d=(d<<3)+(d<<1)+(c^'0'); return d; } int n; template<typename T> class Splay{ private: struct node{ T value; int sz; bool rotag; node *fa,*ch[2]; }; public: node* rt; int n; private: node a[1000000],*stk[1000000]; int top; inline void pushdown(node* t){ if(t->rotag){ node* x=t->ch[0]; t->ch[0]=t->ch[1]; t->ch[1]=x; if(t->ch[0]!=NULL) t->ch[0]->rotag^=1; if(t->ch[1]!=NULL) t->ch[1]->rotag^=1; t->rotag=0; } } inline node* newnode(T v,node* f){ node* now=stk[--top]; now->sz=1; now->value=v; now->fa=f; now->ch[0]=now->ch[1]=NULL; now->rotag=false; return now; } inline void dispose(node*&t){stk[top++]=t;t=NULL;} inline int findson(node* f,node* s){ return(f->ch[1]==s)?1:0; } inline void update(node* t){ t->sz=1; if(t->ch[0]!=NULL)t->sz+=t->ch[0]->sz; if(t->ch[1]!=NULL)t->sz+=t->ch[1]->sz; } inline void rotate(node* t){ node* f=t->fa; node* g=f->fa; int a=findson(f,t),b=a^1; if(t->ch[b]!=NULL)t->ch[b]->fa=f; f->ch[a]=t->ch[b]; t->ch[b]=f; f->fa=t; t->fa=g; if(g!=NULL)g->ch[findson(g,f)]=t;else rt=t; update(f); update(t); } public: Splay(){ for(int i=0;i<1000000;++i)stk[i]=&a[i]; top=1000000; } inline void splay(node* t,node* p){ if(t==NULL)return; pushdown(t); while(t->fa!=p){ node* f=t->fa; node* g=f->fa; if(g==p)rotate(t);else if(findson(g,f)!=findson(f,t)) rotate(t),rotate(t);else rotate(f),rotate(t); } } inline node* find(node* now,int y){ while(now!=NULL){ pushdown(now); int t; if(now->ch[0]==NULL)t=1;else t=now->ch[0]->sz+1; if(t==y)return now; if(t<y)y-=t,now=now->ch[1];else now=now->ch[0]; } } inline void build(node*& p,int l,int r,node* f=NULL){ if(l>r)return; int mid=l+r>>1; p=newnode(mid,f); build(p->ch[0],l,mid-1,p); build(p->ch[1],mid+1,r,p); update(p); } inline void insert(T val){ if(rt==NULL)rt=newnode(val,NULL); int x; for(node* t=rt;t;t=t->son[x]){ x=val>=t->value?1:0; if(t->ch[x]==NULL){t->son[x]=newnode(val,t);splay(t->son[x],rt);break;} } } inline void rev(node* p,int l,int r){ node* pre=find(p,l),*suc=find(p,r); splay(pre,NULL); splay(suc,rt); if(rt->ch[1]->ch[0]!=NULL) rt->ch[1]->ch[0]->rotag^=1; } inline void print(node* p){ if(p==NULL)return; pushdown(p); print(p->ch[0]); if(p->value>1&&p->value<n+2)printf("%d ",p->value-1); print(p->ch[1]); } inline void build(int nn){ n=nn; build(rt,1,n+2); } }; Splay<int>Tree; int main(){ n=readint();int m=readint(); Tree.build(n); while(m--){ int l=readint(),r=readint(); Tree.rev(Tree.rt,l,r+2); } Tree.print(Tree.rt); return 0; }