HDU 4453:Looploop(Splay各种操作)***

http://acm.hdu.edu.cn/showproblem.php?pid=4453

题意:很多种操作:1、add x,将从光标起的 k2 个数全部加上 x;2、reverse,将从光标起的 k1 个数全部反转;3、insert x,在光标处的后一位插入值为 x 的数;4、delete,删除光标所在位置的数;5、move x,如果x是2,将光标右移,否则将光标左移。6、查询光标所在位置的值。

思路:在ACM中第一次写了6000+bytes的代码,把Splay几乎所有操作都汇集了,是一个很好的入门题目(虽然写了好久好久)。Splay是先插入两个结点,即0号节点下面的root,root的右孩子。Splay是一棵二叉树,满足左儿子比节点小,右儿子比节点大,中序遍历出来的结果就是原来数组的结果。所以我们在插入数组的时候,只要将数组插入到 ch[root][1] 的左孩子 ch[ch[root][1][0] (我的代码中的keytree) 的位置,那么就可以对这些数进行区间操作,并且这些数都是按顺序的。Splay就是利用这样的性质来完成各种操作的。注意因为一开始插入了两个点,所以实际上SplayTree的节点有 n + 2 个,数组中的元素标号从 2 开始到 n + 1。还要注意有 Insert 操作所以数组开大点,有一次TLE是因为这个。

  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 1000010
 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 struct SplayTree
 18 {
 19     int fa[N], ch[N][2], col[N], rev[N], sz[N], val[N], cnt, root, num[N];
 20     int n, tol, k1, k2;
 21 
 22     int NewNode(int w, int f, int kind)
 23     {
 24         cnt++;
 25         rev[cnt] = col[cnt] = ch[cnt][0] = ch[cnt][1] = 0;
 26         sz[cnt] = 1; val[cnt] = w; fa[cnt] = f;
 27         ch[f][kind] = cnt;
 28         return cnt;
 29     }
 30 
 31     void PushUp(int x)
 32     {
 33         sz[x] = sz[lson] + sz[rson] + 1;
 34     }
 35 
 36     void PushDown(int x)
 37     {
 38         if(rev[x]) {
 39             swap(lson, rson);
 40             if(lson) rev[lson] ^= 1;
 41             if(rson) rev[rson] ^= 1;
 42             rev[x] = 0;
 43         }
 44         if(col[x]) {
 45             if(lson) {
 46                 col[lson] += col[x];
 47                 val[lson] += col[x];
 48             }
 49             if(rson) {
 50                 col[rson] += col[x];
 51                 val[rson] += col[x];
 52             }
 53             col[x] = 0;
 54         }
 55     }
 56 
 57     void Build(int l, int r, int &x, int f, int kind)
 58     {
 59         if(r < l) return ;
 60         int m = (l + r) >> 1;
 61         x = NewNode(num[m], f, kind);
 62         Build(l, m - 1, ch[x][0], x, 0);
 63         Build(m + 1, r, ch[x][1], x, 1);
 64         PushUp(x);
 65     }
 66 
 67     void Init() // 初始化
 68     {
 69         cnt = root = 0;
 70         col[0] = fa[0] = rev[0] = val[0] = ch[0][0] = ch[0][1] = sz[0] = 0;
 71         root = NewNode(0, 0, 1); // 先开两个节点,然后把数组元素放进 keytree 的位置
 72         ch[root][1] = NewNode(0, root, 1);
 73         sz[root] = 2;
 74         Build(1, n, keytree, ch[root][1], 0);
 75         PushUp(ch[root][1]); PushUp(root);
 76     }
 77 
 78     void Rotate(int x, int kind)
 79     {
 80         int y = fa[x], z = fa[y];
 81         PushDown(y); PushDown(x);
 82         ch[y][!kind] = ch[x][kind];
 83         if(ch[x][kind]) fa[ch[x][kind]] = y;
 84         fa[y] = x; fa[x] = z;
 85         if(z) {
 86             if(ch[z][0] == y) ch[z][0] = x;
 87             else ch[z][1] = x;
 88         }
 89         ch[x][kind] = y;
 90         PushUp(y);
 91     }
 92 
 93     void Splay(int x, int goal)
 94     {
 95         while(fa[x] != goal) {
 96             int y = fa[x], z = fa[y];
 97             PushDown(z); PushDown(y); PushDown(x);
 98             int kind1 = ch[y][0] == x;
 99             int kind2 = ch[z][0] == y;
100             if(z == goal) {
101                 Rotate(x, kind1);
102             } else {
103                 if(kind1 == kind2) {
104                     Rotate(y, kind2);
105                 } else {
106                     Rotate(x, kind1);
107                 }
108                 Rotate(x, kind2);
109             }
110 //            printf("%d, %d, %d
", x, fa[x], goal);
111         }
112         PushUp(x);
113         if(goal == 0) root = x;
114     }
115 
116     void RTO(int k, int goal) // 将第k个元素旋转到0号节点下面
117     {
118         int x = root;
119         PushDown(x);
120         while(1) {
121             if(k <= sz[lson]) x = lson;
122             else if(k == sz[lson] + 1) break;
123             else {
124                 k -= sz[lson] + 1;
125                 x = rson;
126             }
127             PushDown(x);
128         }
129         Splay(x, goal);
130     }
131 
132     void Insert(int val, int index)
133     {
134         RTO(index, 0); RTO(index + 1, root);
135         keytree = NewNode(val, ch[root][1], 0);
136         PushUp(ch[root][1]); PushUp(root);
137 //        Splay(keytree, 0);
138     }
139 
140     int Delete(bool kind)
141     {
142         int w;
143         if(kind) {
144             RTO(1, 0); RTO(3, root);
145             w = val[keytree];
146             keytree = 0;
147         } else {
148             int ed = sz[root];
149             RTO(ed - 2, 0); RTO(ed, root);
150             w = val[keytree];
151             keytree = 0;
152         }
153         PushUp(ch[root][1]); PushUp(root);
154 //        Splay(root, 0);
155         return w;
156     }
157 
158     void Move(int kind) // 光标移动, 如果向左移动就删除最后的元素插到最前面, 向右移动反之
159     {
160         int w;
161         if(kind == 1) {
162             w = Delete(0);
163             Insert(w, 1);
164         } else {
165             w = Delete(1);
166             Insert(w, sz[root] - 1);
167         }
168     }
169 
170     void Reverse()
171     {
172         RTO(1, 0);
173 //        Debug(root);
174         RTO(k1 + 2, root);
175 //        puts("----------------");
176 //        Debug(root);
177 //        puts("----------------");
178         rev[keytree] ^= 1;
179 //        swap(ch[keytree][0], ch[keytree][1]);
180         PushUp(ch[root][1]); PushUp(root);
181     }
182 
183     void Add(int w)
184     {
185         RTO(1, 0); RTO(k2 + 2, root);
186 //        printf("add
");
187         col[keytree] += w;
188         val[keytree] += w;
189         PushUp(ch[root][1]); PushUp(root);
190     }
191 
192     int Query() // 查询操作将要查询的数移动到根节点直接查询
193     {
194         RTO(2, 0);
195 //        printf("%d
", root);
196         return val[root];
197     }
198 
199     void Debug(int x)
200     {
201         if(lson) Debug(lson);
202         printf("%d : %d, %d, %d, %d
", val[x], val[lson], val[rson], lson, rson);
203         if(rson) Debug(rson);
204     }
205 }splay;
206 
207 int main()
208 {
209     int q, cas = 1;
210     while(~scanf("%d%d%d%d", &splay.n, &q, &splay.k1, &splay.k2), splay.n + q + splay.k1 + splay.k2) {
211         for(int i = 1; i <= splay.n; i++) scanf("%d", &splay.num[i]);
212         splay.Init();
213         char s[20];
214         printf("Case #%d:
", cas++);
215         for(int i = 1; i <= q; i++) {
216             scanf("%s", s);
217             int x;
218             if(s[0] == 'q') printf("%d
", splay.Query());
219             else if(s[0] == 'a') {
220                 scanf("%d", &x);
221                 splay.Add(x);
222             } else if(s[0] == 'r') {
223                 splay.Reverse();
224             } else if(s[0] == 'i') {
225                 scanf("%d", &x);
226                 splay.Insert(x, 2);
227             } else if(s[0] == 'd') {
228                 splay.Delete(1);
229             } else if(s[0] == 'm') {
230                 scanf("%d", &x);
231                 splay.Move(x);
232             }
233 //            splay.Debug(splay.root);
234         }
235     }
236     return 0;
237 }
原文地址:https://www.cnblogs.com/fightfordream/p/6061827.html