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 }

转载于:https://www.cnblogs.com/D-O-Time/p/8053145.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值