洛谷3391 文艺平衡树 平衡树模板95

上次被火星人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 }

 

posted @ 2017-08-03 10:32  汪立超  阅读(160)  评论(0编辑  收藏  举报