显示代码纯文本
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <ctime>
#define maxn 100500
using namespace std;
int n,m,l,r;
struct treap{
treap *ch[2];
int v,rd,flip,size;
treap(){size=flip=v=0;rd=rand();ch[0]=ch[1]=NULL;}
void update(){size=ch[0]->size+1+ch[1]->size;}
}*null=new treap(),*root=null,*stack[maxn],*x,*last;
//flip类似于标记,标记要旋转的子树
//stack维护树上的最右端的一条链,序列操作以权值建树,要维持中序遍历不变
//如果遇到以权值建树的情况,sort一遍之后同理
typedef pair<treap*,treap*> tree;
treap* newtreap(int v){
treap *k=new treap();
k->size=1;
k->v=v;
k->ch[0]=k->ch[1]=null;
return k;
}
void pushdown(treap *k){//标记下放
if(k==null) return;
if(k->flip){//有标记则旋转子树
k->flip^=1;
if(k->ch[0]!=null) k->ch[0]->flip^=1;
if(k->ch[1]!=null) k->ch[1]->flip^=1;
swap(k->ch[0],k->ch[1]);
}
}
treap* build(){//新点先插放在最右端,如果其父亲小于其rd,pop出其父亲,
//将其左子树置为其父亲,可手推其中序遍历不变,直至满足查找树性质
int p=0;
for(int i=1;i<=n;i++){
x=newtreap(i);
last=null;
while(p&&stack[p]->rd > x->rd){
stack[p]->update();
last=stack[p];
stack[p--]=null;
}
if(p) stack[p]->ch[1]=x;
x->ch[0]=last;
stack[++p]=x;
}
while(p) stack[p--]->update();
return stack[1];
}
treap* merge(treap *a,treap *b){//合并
if(a==null) return b;
if(b==null) return a;
pushdown(a);
pushdown(b);
//b接在a后面,注意顺序不可变,中序遍历不变
if(a->rd < b->rd){
a->ch[1]=merge(a->ch[1],b);
a->update();
return a;
}
else{
b->ch[0]=merge(a,b->ch[0]);
b->update();
return b;
}
}
tree split(treap *k,int pre){//k为根 ,删除该子树的前pre个数
if(k==null) return tree(null,null);
pushdown(k);
tree y;
if(k->ch[0]->size>=pre){
y=split(k->ch[0],pre);
k->ch[0]=y.second;
k->update();
y.second=k;
}
else{
y=split(k->ch[1],pre-k->ch[0]->size-1);
k->ch[1]=y.first;
k->update();
y.first=k;
}
return y;
}
void change(int le,int ri){
tree x=split(root,ri);
tree y=split(x.first,le-1);
if(y.second!=null) y.second->flip^=1;
root=merge(merge(y.first,y.second),x.second);
}
void dfs(treap *k){
if(k==null) return;
pushdown(k);
if(k->ch[0]!=null) dfs(k->ch[0]);
printf("%d ",k->v);
if(k->ch[1]!=null) dfs(k->ch[1]);
}
int main(){
freopen("sph.in","r",stdin);
freopen("sph.out","w",stdout);
scanf("%d%d",&n,&m);
root=build();
while(m--){
scanf("%d%d",&l,&r);
change(l,r);
}
dfs(root);//中序遍历
}
/*
5 3
1 3
1 3
1 4
*/