建树时节点加1,当需要旋转[a,b]的时候,其实分裂的是[a+1,b+1]的元素,所以增大一个节点,那么最后减一就可以了,如果序列的树很乱,那么用数组下标来建树。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct Node{
Node* ch[2];
int v,s;
int flip;
int cmp(int x) const {
int d=x-ch[0]->s;
if(d==1) return -1;
return (d<=0?0:1);
}
void maintain(){
s=1+ch[0]->s+ch[1]->s;
}
void pushdown(){
if(flip){
flip=0;
swap(ch[0],ch[1]);
ch[0]->flip=!ch[0]->flip;
ch[1]->flip=!ch[1]->flip;
}
}
};
Node* null=new Node();
void rotate(Node* &o,int d)
{
Node* k=o->ch[d^1];o->ch[d^1]=k->ch[d];k->ch[d]=o;
o->maintain();k->maintain();o=k;
}
void splay(Node* &o,int k)
{
o->pushdown();
int d=o->cmp(k);
if(d==1) k-=o->ch[0]->s+1;
if(d!=-1)
{
Node* p=o->ch[d];
p->pushdown();
int d2=p->cmp(k);
int k2=(d2==0?k:k-p->ch[0]->s-1);
if(d2!=-1)
{
splay(p->ch[d2],k2);
if(d==d2) rotate(o,d^1);else rotate(o->ch[d],d);
}
rotate(o,d^1);
}
}
void split(Node* o,int k,Node* &left,Node* &right)
{
splay(o,k);
left=o;
right=o->ch[1];
o->ch[1]=null;
left->maintain();
}
Node* merge(Node* left,Node* right)
{
splay(left,left->s);
left->ch[1]=right;
left->maintain();
return left;
}
void build(Node* &o,int l,int r)
{
if(l>r) {o=null;return ;}
int mid=(l+r)/2;
o=new Node();
o->v=mid;
build(o->ch[0],l,mid-1);
build(o->ch[1],mid+1,r);
o->maintain();
}
void print(Node* o)
{
if(o!=null)
{
o->pushdown();
print(o->ch[0]);
if(o->v>1) printf("%d\n",o->v-1);
print(o->ch[1]);
}
}
void debug(Node* o,int f)
{
if(o!=null)
{
o->pushdown();
debug(o->ch[0],o->v);
printf("%d %d %d\n",o->v,f,o->s);
debug(o->ch[1],o->v);
}
}
void remove(Node* o)
{
if(o->ch[0]!=NULL) remove(o->ch[0]);
if(o->ch[1]!=NULL) remove(o->ch[1]);
delete o;
o=NULL;
}
Node* root;
int main()
{
int n,m;
scanf("%d%d",&n,&m);
build(root,1,n+1);//建树时节点加一
// debug(root,-1);cout<<endl;
while(m--)
{
int a,b;
scanf("%d%d",&a,&b);
Node *left,*mid,*right,*o;
split(root,a,left,o);
split(o,b-a+1,mid,right);
mid->flip^=1;
root=merge(merge(left,right),mid);
// debug(root,-1);cout<<endl;
}
print(root);
return 0;
}