hdu 3487 Play with Chain (Splay)

hdu 3487

Splay树模板题

题意:

  一开始给出1 2 3 4 ... n 这样一个序列,对这个序列进行以下两种操作:

    (1)CUT a b c: 将子串[a,b]切下来,放到剩余串的第c个数之后 。

    (2) FLIP a b : 将子串[a,b]翻转,如 1 2 3 4 就变成 4 3 2 1 。

总之就是一道Splay树的模板题 。。。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cmath>
  5 #include <cstring>
  6 #include <queue>
  7 #include <set>
  8 #include <vector>
  9 #include <map>
 10 #define ll long long
 11
 12 using namespace std;
 13
 14 const int N=100007;
 15
 16 int cnt=1,root=0;
 17 int n,q;
 18
 19 struct tree{
 20     int key,size,fa;
 21     bool flag;
 22     int son[2];
 23 }t[N*3];
 24
 25 inline int newnode(int key,int fa){
 26     int x=cnt++;
 27     t[x].key=key;
 28     t[x].size=1;
 29     t[x].fa=fa;
 30     t[x].son[0]=t[x].son[1]=0;
 31     return x;
 32 }
 33
 34 inline void pushup(int x){
 35     t[x].size=t[t[x].son[0]].size+t[t[x].son[1]].size+1;
 36 }
 37
 38 inline void pushdown(int x){
 39     if (t[x].flag){
 40         t[x].flag=false;
 41         swap(t[x].son[0],t[x].son[1]);
 42         t[t[x].son[0]].flag^=1;
 43         t[t[x].son[1]].flag^=1;
 44     }
 45 }
 46
 47 inline int bulid(int L,int R,int fa){
 48     if (L>R) return 0;
 49     int mid=(L+R)>>1;
 50     int x=newnode(mid,fa);
 51     t[x].son[0]=bulid(L,mid-1,x);
 52     t[x].son[1]=bulid(mid+1,R,x);
 53     pushup(x);
 54     return x;
 55 }
 56
 57 inline void init(){
 58     root=0; cnt=1;
 59     root=bulid(0,n+1,0);
 60 }
 61
 62 inline void rotate(int x,int p){
 63     int y=t[x].fa;
 64     pushdown(y); pushdown(x);
 65     t[y].son[!p]=t[x].son[p];
 66     t[t[x].son[p]].fa=y;
 67     t[x].fa=t[y].fa;
 68     if (t[y].fa)
 69         t[t[x].fa].son[t[t[x].fa].son[1]==y]=x;
 70     t[x].son[p]=y;
 71     t[y].fa=x;
 72     pushup(y);
 73     pushup(x);
 74 }
 75
 76 inline void Splay(int x,int to){
 77     while (t[x].fa!=to){
 78         if (t[t[x].fa].fa==to)
 79             rotate(x,t[t[x].fa].son[0]==x);
 80         else {
 81             int y=t[x].fa, z=t[y].fa;
 82             int p=(t[z].son[0]==y);
 83             if (t[y].son[p]==x){
 84                 rotate(x,!p);
 85                 rotate(x,p);
 86             }
 87             else {
 88                 rotate(y,p);
 89                 rotate(x,p);
 90             }
 91         }
 92     }
 93     if (to==0) root=x;
 94 }
 95
 96 inline int get_kth(int x,int k){
 97     if (x==0 || k>t[x].size) return 0;
 98     while (x){
 99         pushdown(x);
100         if (k==t[t[x].son[0]].size+1) break;
101         if (k>t[t[x].son[0]].size+1){
102             k-=t[t[x].son[0]].size+1;
103             x=t[x].son[1];
104         }
105         else
106             x=t[x].son[0];
107     }
108
109     return x;
110 }
111
112 inline void CUT(int L,int R,int c){
113     Splay(get_kth(root,L),0);
114     Splay(get_kth(root,R+2),root);
115     int tmp=t[t[root].son[1]].son[0];
116     t[t[root].son[1]].son[0]=0;
117     pushup(t[root].son[1]);
118     pushup(root);
119
120     Splay(get_kth(root,c+1),0);
121     Splay(get_kth(root,c+2),root);
122     t[tmp].fa=t[root].son[1];
123     t[t[root].son[1]].son[0]=tmp;
124     pushup(t[root].son[1]);
125     pushup(root);
126 }
127
128 inline void FILP(int L,int R){
129     Splay(get_kth(root,L),0);
130     Splay(get_kth(root,R+2),root);
131     t[t[t[root].son[1]].son[0]].flag^=1;
132     pushup(t[root].son[1]);
133     pushup(root);
134 }
135
136 int cou=0;
137 inline void output(int x){
138     if (x==0) return;
139     pushdown(x);
140     output(t[x].son[0]);
141     if (t[x].key>=1 && t[x].key<=n) {
142         cou++;
143         printf("%d",t[x].key);
144         if (cou<n) printf(" ");
145         else puts("");
146     }
147     output(t[x].son[1]);
148 }
149
150 char ch[20];
151
152 int main(){
153     int x,y,z;
154     while (scanf("%d%d",&n,&q)!=EOF){
155         if (n==-1) break;
156         init();
157         while (q--){
158             scanf("%s",ch);
159             if (ch[0]==‘C‘){
160                 scanf("%d%d%d",&x,&y,&z);
161                 CUT(x,y,z);
162             }
163             else {
164                 scanf("%d%d",&x,&y);
165                 FILP(x,y);
166             }
167         }
168         cou=0;
169         output(root);
170     }
171     return 0;
172 }
时间: 2024-10-03 08:14:33

hdu 3487 Play with Chain (Splay)的相关文章

hdu 3487 Play with Chain(splay区间剪切,翻转)

题目链接:hdu 3487 Play with Chain 题意: cut a b c: 将a到b区间剪切下来,放在第c位置的后面. flip a b: 翻转a到b区间 题解: 第一个操作,选通过旋转,然后使a到b区间变成根的右儿子的左儿子,然后剪掉. 再找到c+1的位置,接上. 第二个操作,区间标记就行. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4

hdu 3487 Play with Chain

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3487 YaoYao is fond of playing his chains. He has a chain containing n diamonds on it. Diamonds are numbered from 1 to n.At first, the diamonds on the chain is a sequence: 1, 2, 3, …, n.He will perform t

Splay树——HDU 3487 Play with Chain

对应HDU题目:点击打开链接 Play with Chain Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4571    Accepted Submission(s): 1859 Problem Description YaoYao is fond of playing his chains. He has a chain cont

HDU 3487 Play with Chain 【Splay】

1-n的序列,有两种操作: 1,将一段区间翻转 2,将一段区间切下来放到剩余序列的第C个数后 采用延迟更新的方法维护区间的翻转,并维护一个size域. 添加一个最大点和一个最小点,防止出界 翻转时,将第L-1个点伸展到跟,再将第R+1个点伸展到L-1的右子树,这时R+1的左子树就是要翻转的区间,加上一个标记. 切区间时,跟翻转操作差不多,只是不加标记.然后找到C+1和C,将C伸展到根,C+1伸展到C的右子树,此时C+1的左子树就是要插入的位置. 其实我说了这么多并没有什么卵用....最后还是得自

hdu3487Play with Chain(splay)

链接 简单的两种操作,一种删除某段区间,加在第I个点的后面,另一个是翻转区间.都是splay的简单操作. 悲剧一:pushdown时候忘记让lz=0 悲剧二:删除区间,加在某点之后的时候忘记修改其父亲节点. 1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vec

HDOJ 3487 Play with Chain

前言 在编程过程中总结归纳出来的一种编程经验,从而形成的设计思想称为设计模式. 设计模式有23种.它适用于所有的编程语言. 常用的有创新型的设计模式:简单工厂.抽象工厂和单例模式:行为型的设计模式:模板设计模式.观察者模式和命令模式:结构性的设计模式:适配器设计模式.代理模式(静态和动态两种,典型的有在spring的AOP编程中使用)和装饰器设计模式. 正文 单例模式(singleton) 保证一个类在内存中只能创建一个实例. 1.实现步骤: 1)将构造器私有化,即使用private修饰构造器

HDU 3487:Play with Chain(Splay)

http://acm.hdu.edu.cn/showproblem.php?pid=3487 题意:有两种操作:1.Flip l r ,把 l 到 r 这段区间 reverse.2.Cut a b c ,把 a 到 b 这段区间切掉,再把这段区间接到切掉后的第 c 个数的后面. 思路:做完了上一道变态题目,做这道题目如鱼得水.Cut的时候就是把a 到 b 放到keytree的位置,记录一下当前keytree的值,然后切掉,再把切掉后的第 c 个数转到 root 的位置,再把这个记录的值重新连接回

【HDU 3487】Play with Chain Splay

题意 给定$n$个数序列,每次两个操作,将区间$[L,R]$拼接到去掉区间后的第$c$个数后,或者翻转$[L,R]$ Splay区间操作模板,对于区间提取操作,将$L-1$ Splay到根,再将$R+1$ Splay到根节点的右儿子,那么根节点右儿子的左儿子就对应区间$[L,R]$,对于反转操作,通过懒操作下放 代码 #include <bits/stdc++.h> #define inf 0x7f7f7f7f using namespace std; const int N = 500005

HDU 3487(Play with Chain-Splay)[template:Splay]

Play with Chain Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4679    Accepted Submission(s): 1892 Problem Description YaoYao is fond of playing his chains. He has a chain containing n diamon