题解:
每次reverse(l,r)
把l-1转到根,r+1变成他的右儿子,给r+1的左儿子打个标记就是一次反转操作了
每次find和dfs输出的时候下放标记,把左儿子和右儿子换一下
记得建树的时候建0到n+1
#include<cstdio> #include<algorithm> #include<cstring> #define N 100010 #define which(x) (ls[fa[(x)]]==(x)) using namespace std; int sz[N],ls[N],rs[N],fa[N],n,m,root,flag[N],id[N],idx; void upt(int x) {sz[x]=1+sz[ls[x]]+sz[rs[x]];} int read() { int ret=0,neg=1; char j=getchar(); for (;j>'9' || j<'0';j=getchar()) if (j=='-') neg=-1; for (;j>='0' && j<='9';j=getchar()) ret=ret*10+j-'0'; return ret*neg; } void write(int x) { if (x<0) x=-x; if (x>=10) write(x/10); putchar(x%10+'0'); } void swap_son(int u) { if (!u) return; flag[u]^=1; swap(ls[u],rs[u]); upt(u); } void pushdown(int u) { if (!flag[u]) return ; swap_son(ls[u]),swap_son(rs[u]); flag[u]=0; } int Build(int l, int r) { int mid=l+r>>1,u=++idx; id[u]=mid; if(mid>l) ls[u]=Build(l,mid-1),fa[ls[u]]=u; if(mid<r) rs[u]=Build(mid+1,r),fa[rs[u]]=u; upt(u); return u; } void Rotate(int u) { int v=fa[u],w=fa[v],b=which(u)?rs[u]:ls[u]; if(w) which(v)?ls[w]=u:rs[w]=u; which(u)?(ls[v]=b,rs[u]=v):(rs[v]=b,ls[u]=v); fa[u]=w,fa[v]=u; if(b) fa[b]=v; upt(v),upt(u); } void Splay(int u, int tar) { while(fa[u] != tar) { if(fa[fa[u]] != tar) { if(which(u) == which(fa[u])) Rotate(fa[u]); else Rotate(u); } Rotate(u); } if(!tar) root = u; } int find(int k) { int u=root; pushdown(u); while (sz[ls[u]]+1!=k && u) { if (sz[ls[u]]>=k) u=ls[u]; else k-=sz[ls[u]]+1,u=rs[u]; pushdown(u); } return u; } void rev(int l,int r) { int u=find(l-1),v=find(r+1); Splay(u,0); Splay(v,u); swap_son(ls[rs[root]]); } void dfs(int u) { pushdown(u); if (ls[u]) dfs(ls[u]); if (id[u]>1 && id[u]<n+2) write(id[u]-1),putchar(' '); if (rs[u]) dfs(rs[u]); } int main() { scanf("%d%d",&n,&m); root=Build(1,n+2); for (int i=1,l,r;i<=m;i++) l=read(),r=read(),rev(l+1,r+1); dfs(root); return 0; }