Splay(区间翻转) 模板

Posted D O Time

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Splay(区间翻转) 模板相关的知识,希望对你有一定的参考价值。

洛谷:P3391 【模板】文艺平衡树(Splay)

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 using namespace std;
 5 const int MAXN=110000;
 6 int n,m,tp,root,CNT;
 7 int key[MAXN],lz[MAXN],fa[MAXN],sz[MAXN],val[MAXN],q[MAXN],Q[MAXN],ch[MAXN][2];
 8 void update(int k){ sz[k]=sz[ch[k][0]]+sz[ch[k][1]]+1; }
 9 void rotate(int x,int &y)
10 {
11   int old=fa[x],oldf=fa[old],op=ch[old][1]==x;
12   if(old==y) y=x;
13   else ch[oldf][ch[oldf][1]==old]=x;
14   fa[x]=oldf;
15   fa[ch[x][op^1]]=old; ch[old][op]=ch[x][op^1];
16   fa[old]=x; ch[x][op^1]=old;
17   update(old); update(x);
18 }
19 void down(int x)
20 {
21   if(lz[x])
22     {      
23       lz[x]^=1; lz[ch[x][0]]^=1; lz[ch[x][1]]^=1;
24       swap(ch[x][0],ch[x][1]);
25     }
26 }
27 void splay(int x,int &y)
28 {
29   int now=x,old,oldf;Q[++tp]=now;
30   while(now!=y) Q[++tp]=fa[now] , now=fa[now];
31   while(tp--) down(Q[tp]);
32   while(x!=y)
33     {
34       old=fa[x],oldf=fa[old];
35       if(old!=y){
36         if((ch[old][0]==x)^(ch[oldf][0]==old)) rotate(x,y);
37         else rotate(old,y);
38       }
39       rotate(x,y);
40     }
41 }
42 void Build(int &k,int ll,int rr,int FA)
43 {
44   int mid=(ll+rr)/2;
45   k=++CNT; fa[k]=FA; key[k]=val[mid];
46   if(mid>ll) Build(ch[k][0],ll,mid-1,k);
47   if(mid<rr) Build(ch[k][1],mid+1,rr,k);
48   update(k);
49 }
50 int findx(int x)//注意下放。
51 {
52   int now=root;
53   while(1)
54     {
55       down(now);
56       if(x<=sz[ch[now][0]]) now=ch[now][0];
57       else
58         {
59           x-=sz[ch[now][0]]+1;
60           if(x==0) return now;
61           else now=ch[now][1]; 
62         }
63     }
64 }
65 void rev(int L,int R)
66 {
67   int ll=findx(L-1),rr=findx(R+1);
68   splay(ll,root);
69   splay(rr,ch[root][1]);
70   lz[ch[ch[root][1]][0]]^=1;
71 }
72 void dfs(int u)
73 {
74   down(u);  
75   if(ch[u][0]) dfs(ch[u][0]);
76   if(key[u]!=0&&key[u]!=n+1) printf("%d ",key[u]);
77   if(ch[u][1]) dfs(ch[u][1]);
78 }
79 int main()
80 {
81   scanf("%d%d",&n,&m);
82   for(int i=1;i<=n;i++)val[i]=i;
83   Build(root,0,n+1,0);
84   for(int i=1,L,R;i<=m;i++)
85     {
86       scanf("%d%d",&L,&R);
87       L++; R++; rev(L,R);
88     }
89   dfs(root); puts("");
90   return 0;
91 }

以上是关于Splay(区间翻转) 模板的主要内容,如果未能解决你的问题,请参考以下文章

P3391 模板文艺平衡树(Splay)

P3391 模板文艺平衡树(Splay)

洛谷 P3391 模板文艺平衡树(Splay)

P3391 模板文艺平衡树(Splay)

洛谷:P3384 模板文艺平衡树(Splay)

[Splay]luogu P3391 文艺平衡树