UVA - 11922 Permutation Transformer (splay)

本文详细介绍了如何使用Splay树解决区间翻转问题,通过动态调整树结构实现高效区间操作,适用于需要频繁进行区间修改的数据结构题目。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

题意:你的任务是根据m条指令改变排列{!,2,3,...,n}。每条指令(a,b)表示取出第a~b个元素,翻转后添加到排列的尾部。输出最终序列。

解法:splay对区间分裂合并翻转,模板题。

初学splay,代码写得有点挫,以后慢慢改~~

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 struct Splay {
 4     static const int N=1e5+10;
 5     int ch[N][2],siz[N],val[N],fa[N],tot,flip[N],n,m;
 6     int rel(int u) {
 7         return ch[fa[u]][1]==u;
 8     }
 9     void init() {
10         tot=fa[0]=ch[0][0]=ch[0][1]=siz[0]=val[0]=flip[0]=0;
11     }
12     int newnode(int x) {
13         int u=++tot;
14         fa[u]=ch[u][0]=ch[u][1]=0;
15         siz[u]=1,val[u]=x,flip[u]=0;
16         return u;
17     }
18     void pu(int u) {
19         siz[u]=siz[ch[u][0]]+siz[ch[u][1]]+1;
20     }
21     void pd(int u) {
22         if(flip[u]) {
23             flip[u]=0;
24             swap(ch[u][0],ch[u][1]);
25             flip[ch[u][0]]^=1;
26             flip[ch[u][1]]^=1;
27         }
28     }
29     void rot(int u) {
30         int v=fa[u],f=rel(u),ff=rel(v);
31         ch[v][f]=ch[u][f^1],fa[ch[v][f]]=v;
32         ch[u][f^1]=v,fa[u]=fa[v],fa[v]=u;
33         if(fa[u])ch[fa[u]][ff]=u;
34         pu(v),pu(u);
35     }
36     void splay(int& rt,int u) {
37         for(int v=fa[rt]; fa[u]!=v; rot(u))
38             if(fa[fa[u]]!=v&&rel(fa[u])==rel(u))rot(fa[u]);
39         rt=u;
40     }
41     int kth(int u,int k) {
42         for(pd(u); k!=siz[ch[u][0]]+1; pd(u)) {
43             if(k<siz[ch[u][0]]+1)u=ch[u][0];
44             else k-=siz[ch[u][0]]+1,u=ch[u][1];
45         }
46         return u;
47     }
48     int next(int u) {
49         if(ch[u][1]) {
50             for(u=ch[u][1],pd(u); ch[u][0]; u=ch[u][0],pd(u));
51             return u;
52         } else {
53             for(; fa[u]&&rel(u); u=fa[u]);
54             return fa[u];
55         }
56     }
57     void split(int& l,int k,int& r) {
58         splay(l,kth(l,k));
59         r=ch[l][1],fa[l]=fa[r]=ch[l][1]=0;
60         pu(l);
61     }
62     void merge(int& l,int r) {
63         splay(l,kth(l,siz[l]));
64         ch[l][1]=r,fa[r]=l;
65         pu(l);
66     }
67     void go() {
68         init();
69         scanf("%d%d",&n,&m);
70         int rt=newnode(0);
71         for(int i=1; i<=n; ++i)merge(rt,newnode(i));
72         while(m--) {
73             int l,r;
74             scanf("%d%d",&l,&r);
75             int u,v;
76             split(rt,l,u);
77             split(u,r-l+1,v);
78             flip[u]^=1;
79             merge(rt,v);
80             merge(rt,u);
81         }
82         for(int u=next(kth(rt,1)); u; u=next(u))printf("%d\n",val[u]);
83     }
84 } splay;
85 
86 int main() {
87     splay.go();
88     return 0;
89 }

 

转载于:https://www.cnblogs.com/asdfsag/p/10273903.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值