上次被火星人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 }
来源:https://www.cnblogs.com/wanglichao/p/7278382.html