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 的位置,再把这个记录的值重新连接回去。要注意当全部询问结束了,要把所有的rev标记pushdown。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cmath>
  4 #include <cstdlib>
  5 #include <algorithm>
  6 #include <string>
  7 #include <iostream>
  8 #include <stack>
  9 #include <map>
 10 #include <queue>
 11 using namespace std;
 12 #define N 300100
 13 #define INF 0x3f3f3f3f
 14 #define lson ch[x][0]
 15 #define rson ch[x][1]
 16 #define keytree ch[ch[root][1]][0]
 17
 18 struct SplayTree
 19 {
 20     int num[N], rev[N], ch[N][2], fa[N], val[N], sz[N];
 21     int n, root, cnt, ans[N], tol;
 22
 23     void PushDown(int x)
 24     {
 25         if(rev[x]) {
 26             swap(lson, rson);
 27             if(lson) rev[lson] ^= 1;
 28             if(rson) rev[rson] ^= 1;
 29             rev[x] = 0;
 30         }
 31     }
 32
 33     void PushUp(int x)
 34     {
 35         sz[x] = sz[lson] + sz[rson] + 1;
 36     }
 37
 38     int NewNode(int w, int f, int kind)
 39     {
 40         int x = ++cnt;
 41         ch[x][0] = ch[x][1] = rev[x] = 0;
 42         sz[x] = 1; val[x] = w; fa[x] = f;
 43         ch[f][kind] = cnt;
 44         return x;
 45     }
 46
 47     void Build(int l, int r, int &x, int f, int kind)
 48     {
 49         if(l > r) return ;
 50         int m = (l + r) >> 1;
 51         x = NewNode(num[m], f, kind);
 52         Build(l, m - 1, ch[x][0], x, 0);
 53         Build(m + 1, r, ch[x][1], x, 1);
 54         PushUp(x);
 55     }
 56
 57     void Init()
 58     {
 59         root = cnt = tol = 0;
 60         rev[0] = val[0] = fa[0] = sz[0] = ch[0][0] = ch[0][1] = 0;
 61         root = NewNode(0, 0, 0);
 62         ch[root][1] = NewNode(0, root, 1);
 63         sz[root] = 2;
 64         Build(1, n, keytree, ch[root][1], 0);
 65         PushUp(ch[root][1]); PushUp(root);
 66     }
 67
 68     void Rotate(int x, int kind)
 69     {
 70         int y = fa[x], z = fa[y];
 71         PushDown(y); PushDown(x);
 72         ch[y][!kind] = ch[x][kind];
 73         if(ch[y][!kind]) fa[ch[y][!kind]] = y;
 74         if(z) {
 75             if(y == ch[z][0]) ch[z][0] = x;
 76             else ch[z][1] = x;
 77         }
 78         fa[x] = z; fa[y] = x;
 79         ch[x][kind] = y;
 80         PushUp(y);
 81     }
 82
 83     void Splay(int x, int goal)
 84     {
 85         while(fa[x] != goal) {
 86             int y = fa[x], z = fa[y];
 87             PushDown(z); PushDown(y); PushDown(x);
 88             int kind1 = x == ch[y][0];
 89             int kind2 = y == ch[z][0];
 90             if(z == goal) {
 91                 Rotate(x, kind1);
 92             } else {
 93                 if(kind1 == kind2) {
 94                     Rotate(y, kind1);
 95                 } else {
 96                     Rotate(x, kind1);
 97                 }
 98                 Rotate(x, kind2);
 99             }
100         }
101         PushUp(x);
102         if(goal == 0) root = x;
103     }
104
105     void RTO(int k, int goal)
106     {
107         int x = root;
108         PushDown(x);
109         while(k != sz[lson] + 1) {
110             if(k <= sz[lson]) x = lson;
111             else k -= sz[lson] + 1, x = rson;
112             PushDown(x);
113         }
114         Splay(x, goal);
115     }
116
117     void Cut(int l, int r, int c)
118     {
119         RTO(l, 0);
120 //        Debug();
121         RTO(r + 2, root);
122         int tmp = keytree;
123         keytree = 0;
124 //        Debug();
125         RTO(c + 1, 0);
126 //        Debug();
127         RTO(c + 2, root);
128         fa[tmp] = ch[root][1];
129         keytree = tmp;
130     }
131
132     void Reverse(int l, int r)
133     {
134         RTO(l, 0); RTO(r + 2, root);
135         rev[keytree] ^= 1;
136     }
137
138     void Down(int x)
139     {
140         PushDown(x);
141         if(lson) Down(lson);
142         if(rson) Down(rson);
143     }
144
145     void Travel(int x)
146     {
147         if(lson) Travel(lson);
148         ans[tol++] = val[x];
149         if(rson) Travel(rson);
150     }
151
152     void Debug()
153     {
154         Down(root);
155         Travel(root);
156         for(int i = 1; i <= n; i++) {
157             if(i == n) printf("%d\n", ans[i]);
158             else printf("%d ", ans[i]);
159         }
160     }
161 }spy;
162
163 int main()
164 {
165     int n, m;
166     while(scanf("%d%d", &n, &m)) {
167         if(n < 0 || m < 0) break;
168         spy.n = n;
169         for(int i = 1; i <= n; i++) spy.num[i] = i;
170         spy.Init();
171         while(m--) {
172             char s[10];
173             int a, b, c;
174             scanf("%s", s);
175             if(s[0] == ‘C‘) {
176                 scanf("%d%d%d", &a, &b, &c);
177                 spy.Cut(a, b, c);
178             } else {
179                 scanf("%d%d", &a, &b);
180                 spy.Reverse(a, b);
181             }
182         }
183         spy.Debug();
184     }
185     return 0;
186 }
时间: 2024-12-08 07:36:06

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

HDU 1231:最大连续子序列(DP)

最大连续子序列 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 18461    Accepted Submission(s): 8202 Problem Description 给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j

HDU 5968:异或密码(暴力)

http://acm.hdu.edu.cn/showproblem.php?pid=5968 题意:中文题意. 思路:一开始不会做,后来发现数据范围很小,而且那个数要是连续的,所以可能把所有情况枚举出来很小吧.打了个表发现 100 只有 4950 个,然后直接暴力枚举每一种情况,放在Hash里面标记是否出现过这个数,再弄一个len数组放置每一种情况长度,然后对答案分别向左和向右找最长的长度就好了. 1 #include <cstdio> 2 #include <cstring> 3

HDU 2063:过山车(二分匹配,匈牙利算法)

过山车 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 9745    Accepted Submission(s): 4294 Problem Description RPG girls今天和大家一起去游乐场玩,终于可以坐上梦寐以求的过山车了.可是,过山车的每一排只有两个座位,而且还有条不成文的规矩,就是每个女生必须找个个男生做par

HDU 1272: 小希的迷宫(并查集)

小希的迷宫 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 25010    Accepted Submission(s): 7683 Problem Description 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是

HDU 1253:胜利大逃亡(简单三维BFS)

胜利大逃亡 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 24937    Accepted Submission(s): 9535 Problem Description Ignatius被魔王抓走了,有一天魔王出差去了,这可是Ignatius逃亡的好机会. 魔王住在一个城堡里,城堡是一个A*B*C的立方体,可以被表示成A个B*C的

带权并查集(含种类并查集)【经典模板】 例题:①POJ 1182 食物链(经典)②HDU - 1829 A bug&#39;s life(简单) ③hihoCoder 1515 : 分数调查

带权并查集: 增加一个 value 值,并且每次合并和查找的时候需要去维护这个 value 例题一 :POJ 1182 食物链(经典) 题目链接:https://vjudge.net/contest/339425#problem/E 带权并查集的解法 定义两个数组fa[ ]和rela[ ],fa用来判断集合关系,rela用来描述其与根节点的关系.因为关系满足传递性,所以可以推导出给出条件下的当前关系,在判断与之前已有关系是否矛盾. 本题的解法巧妙地利用了模运算,rela数组用0表示同类,1表示当

hdu 4974 A simple water problem(数学题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4974 Problem Description Dragon is watching competitions on TV. Every competition is held between two competitors, and surely Dragon's favorite. After each competition he will give a score of either 0 or

设计模式学习第一天:23种设计模式(全)

C#常见的设计模式 一.概要: 模式分为三种,设计模式.体系结构模式与惯用法.其中惯用法是一种语言紧密相关的模式,例如,定界加锁模式其实是一种惯用法. 在C#项目开发过程中,很多情况下您已经使用了某些模式,但或许您并不知道自己所使用的这种解决方案是一种已经被总结归纳的模式. 工厂.策略.桥接.模板方法.代理等等23种Gof经典模式是属于设计模式,设计模式的粒度相对较小,基本上用于提高模块内部的可扩展性和可维护性需求 三层.MVC.IoC/DI等属于体系结构模式,粒度比设计模式大,它是从项目的整体

hdu 4857 逆拓扑+大根堆(priority_queue)

题意:排序输出:在先满足定约束条件下(如 3必需在1前面,7必需在4前面),在满足:1尽量前,其次考虑2,依次.....(即有次约束). 开始的时候,只用拓扑,然后每次在都可以选的时候,优先考虑小的,其实没什么简单,如 图(3-->1,2)这样输出是2.3.1,正确应该是 3 1 2,因为 1要尽量前(都满足第一约束). 参考他人思路结合自己理解:因为这样的弊端就是没有考虑这种情况:图中:若我的"子孙"中,有的比你次优先,虽然现在我们都可以输出,但是要考虑我的子代,若我的子代有次