BZOJ3223 文艺平衡树
splay的区间翻转,splay(l-1,f[rot]),splay(r+1,rot);
之后将ch[ch[rot][1]][0]的子树翻转
理论简单,操作闹腾...
附上代码,splay区间操作入门题
1 #include <cstdio> 2 #include <algorithm> 3 #include <cmath> 4 #include <cstring> 5 #include <iostream> 6 #include <queue> 7 #include <cstdlib> 8 using namespace std; 9 #define N 100050 10 #define get(rt) (ch[f[rt]][0]!=rt) 11 #define PushUp(rt) if(rt)siz[rt]=siz[ch[rt][0]]+siz[ch[rt][1]]+1 12 int ch[N][2],f[N],siz[N],val[N]; 13 int rot,n,Q; 14 bool tag[N]; 15 void PushDown(int x) 16 { 17 if(!tag[x])return ; 18 tag[x]=0; 19 swap(ch[x][0],ch[x][1]); 20 tag[ch[x][0]]^=1; 21 tag[ch[x][1]]^=1; 22 } 23 void rotate(int rt) 24 { 25 int x=f[rt],y=f[x],b=get(rt); 26 ch[x][b]=ch[rt][b^1];f[ch[x][b]]=x;ch[rt][b^1]=x;f[x]=rt;f[rt]=y; 27 if(y)ch[y][ch[y][0]!=x]=rt; 28 PushUp(x);PushUp(rt); 29 if(rot==x)rot=rt; 30 } 31 void splay(int rt,int y) 32 { 33 for(int fa;(fa=f[rt])!=y;rotate(rt)) 34 { 35 if(f[fa]!=y) 36 { 37 rotate((get(rt)==get(fa))?fa:rt); 38 } 39 } 40 } 41 int find(int x) 42 { 43 int now=rot; 44 while(1) 45 { 46 PushDown(now); 47 if(x<=siz[ch[now][0]])now=ch[now][0]; 48 else 49 { 50 x-=siz[ch[now][0]]+1; 51 if(!x)return now; 52 now=ch[now][1]; 53 } 54 } 55 } 56 void build(int fa,int l,int r) 57 { 58 if(l>r)return ; 59 int m=(l+r)>>1; 60 ch[fa][m>fa]=m; 61 siz[m]=1; 62 val[m]=m-1; 63 f[m]=fa; 64 build(m,l,m-1); 65 build(m,m+1,r); 66 PushUp(m); 67 } 68 void reverse(int x,int y) 69 { 70 x=find(x); 71 y=find(y); 72 splay(x,f[rot]); 73 splay(y,rot); 74 tag[ch[y][0]]^=1; 75 } 76 int main() 77 { 78 scanf("%d%d",&n,&Q); 79 build(0,1,n+2); 80 rot=(n+3)>>1; 81 for(int i=1;i<=Q;i++) 82 { 83 int x,y; 84 scanf("%d%d",&x,&y); 85 reverse(x,y+2); 86 } 87 for(int i=2;i<=n;i++)printf("%d ",val[find(i)]); 88 printf("%d\n",val[find(n+1)]); 89 }