上次被火星人prefix吊打,突然发现已经不会写splay了
于是来道模板题
区间反转?
打一些lazy标记,感觉和线段树没有差太多,而且交换左右儿子这操作真是妙
lazy标记
下传的时间要注意有些东西会变
1 #include <bits/stdc++.h> 2 #define N 500000 3 #define mid (l+r>>1) 4 using namespace std; 5 int n,m,x,y; 6 struct spla 7 { 8 int fa[N],c[N][2],size[N],tr[N]; 9 bool rev[N]; 10 int NODE,rt; 11 void up(int x) 12 { 13 size[x]=size[c[x][0]]+size[c[x][1]]+1; 14 } 15 void down(int x) 16 { 17 if(rev[x]) swap(c[x][0],c[x][1]),rev[x]=0,rev[c[x][0]]^=1,rev[c[x][1]]^=1; 18 } 19 void rot(int x) 20 { 21 int y=fa[x]; 22 down(y);down(x); 23 bool k=c[y][1]==x; 24 if(fa[y]) c[fa[y]][c[fa[y]][1]==y]=x; else rt=x; 25 fa[x]=fa[y];fa[y]=x;c[y][k]=c[x][!k];fa[c[x][!k]]=y;c[x][!k]=y; 26 up(y);up(x); 27 } 28 void splay(int x,int y) 29 { 30 for(int t;(t=fa[x])!=y;rot(x)) 31 if(fa[t]!=y) 32 rot(c[t][1]==x^c[fa[t]][1]==t?x:t); 33 } 34 int build(int l,int r) 35 { 36 int now=++NODE;tr[now]=mid;size[now]=r-l+1;rev[now]=0; 37 if(l<mid) 38 { 39 int ls=build(l,mid-1); 40 fa[ls]=now; 41 c[now][0]=ls; 42 } 43 if(mid<r) 44 { 45 int rs=build(mid+1,r); 46 fa[rs]=now; 47 c[now][1]=rs; 48 } 49 return now; 50 } 51 int pos(int x) 52 { 53 int now,k; 54 for(now=rt;down(now),size[c[now][0]]+1!=x;k=x>size[c[now][0]],x-=k*(size[c[now][0]]+1),now=c[now][k]); 55 return now; 56 } 57 void reverse(int x,int y) 58 { 59 splay(pos(x),0); 60 splay(pos(y+2),rt); 61 rev[c[c[rt][1]][0]]^=1; 62 } 63 void dfs(int now) 64 { 65 down(now); 66 if(c[now][0]) dfs(c[now][0]); 67 if(tr[now]>0 && tr[now]<=n) 68 printf("%d ",tr[now]); 69 if(c[now][1]) dfs(c[now][1]); 70 } 71 } sp; 72 int main() 73 { 74 scanf("%d%d",&n,&m); 75 sp.rt=sp.build(0,n+1); 76 for(int i=1;i<=m;i++) 77 scanf("%d%d",&x,&y),sp.reverse(x,y); 78 sp.dfs(sp.rt); 79 return 0; 80 }