ddosvoid和自为风月马前卒教了我这道题
他们好强啊
如果我们要反转区间[l,r]
我们首先把l的前驱旋转到根节点
再把r的后继旋转到根节点的右儿子
那么此时根节点的右儿子的左儿子所代表的就是区间l,r
具体为啥不知道
然后可以给splay的节点打标记,就像线段树一样
inline void pushdown(int x){ if(!tree[x].tag) return; swap(tree[x].e[0],tree[x].e[1]); tree[tree[x].e[0]].tag^=1; tree[tree[x].e[1]].tag^=1; tree[x].tag=0; }
这就是标记下传
#include<cstdlib> #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using std::swap; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } int root;int n;int m; struct Splay{ struct node{ int e[2],size,fa; bool tag; }tree[200000]; inline int iden(int x){ return x==tree[tree[x].fa].e[1]; } inline void update(int x){ tree[x].size=tree[tree[x].e[0]].size+tree[tree[x].e[1]].size+1; } inline void connect(int x,int fa,int how){ tree[x].fa=fa; tree[fa].e[how]=x; } void rotate(int x){ int y=tree[x].fa; if(y==root) root=x; int r=tree[y].fa; //pushdown(r); pushdown(y); pushdown(x); int sony=iden(x); int sonr=iden(y); int b=tree[x].e[sony^1]; connect(b,y,sony); connect(y,x,sony^1); connect(x,r,sonr); update(y); update(x); } inline void pushdown(int x){ if(!tree[x].tag) return; swap(tree[x].e[0],tree[x].e[1]); tree[tree[x].e[0]].tag^=1; tree[tree[x].e[1]].tag^=1; tree[x].tag=0; } void splay(int pos,int to){ while(tree[pos].fa!=to){ if(tree[tree[pos].fa].fa==to) rotate(pos); else if(iden(pos)==iden(tree[pos].fa)){ rotate(tree[pos].fa); rotate(pos); } else { rotate(pos); rotate(pos); } } update(pos); } int build(int l,int r){ if(l>r) return 0; int mid=(l+r)>>1; int lson=build(l,mid-1); connect(lson,mid,0); int rson=build(mid+1,r); connect(rson,mid,1); tree[mid].tag=0; update(mid); return mid; } int find(int val){ int now=root;val--; pushdown(now); while(val!=tree[tree[now].e[0]].size){ if(tree[tree[now].e[0]].size<val){ val-=tree[tree[now].e[0]].size+1; now=tree[now].e[1]; } else now=tree[now].e[0]; pushdown(now); } return now; } void print(int now){ if(!now) return; pushdown(now); print(tree[now].e[0]); if(now!=1&&now!=n+2) printf("%d ",now-1); print(tree[now].e[1]); } }s; int main(){ n=read(); m=read(); root=s.build(1,n+2); while(m--){ int l=read(),r=read(); int x=s.find(l); s.splay(x,0); int y=s.find(r+2); s.splay(y,root); s.tree[s.tree[y].e[0]].tag^=1; } s.print(root); return 0; }