题目大意:给定一个$1\sim 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;
}