Splay Tree (POJ 3580 & UVA 12356 & HDU 1890)

  最近几天熟悉着用Linux,所以做题的量少了下来。这几天新学习了Splay Tree这种数据结构,于是在看懂了Splay操作以后就找了几道题来练手,除了UVA那题是1y顺利通过的,其他两题都出现了各种不同的错误,不过最终还是通过了!

  POJ 3580是我入手Splay Tree的第一道题,这道题需要的操作包括:

  1.区间增加相同的数

  2.区间反转

  3.区间滚动

  4.插入一个数

  5.删除一个数

  6.查询一个区间内的最小值

  我的Splay操作是学习《运用伸展树解决数列维护问题》的论文的,里面教的Splay和Rotate操作包括单纯的和加上更新操作两种。知道了Splay操作以后,延迟操作跟线段树的是一样的,所以不必重新再学。刚学会Splay操作的时候,还不太懂Splay的原理,所以在写insert和delete的时候各种囧态浮现。。。囧!刚开始的时候,我的insert和delete还是很笨重的写了一大串其他平衡树用的insert和delete的方法,出现各种bug以后,我忽而醒觉了,原来Everything is Splay! 这句不知道在哪里听过的话是那么的正确。用Splay Tree就是要将各种操作简化,insert或者delete的时候,只要把要insert和delete的位置Splay出来,剩下要做的事就相当简单了!

POJ 3580: poj.org/problem?id=3580

View Code
  1 #define prog 1
  2 
  3 #if prog == 1
  4 
  5 #include <cstdio>
  6 #include <cstdlib>
  7 #include <cstring>
  8 #include <cassert>
  9 #include <algorithm>
 10 
 11 using namespace std;
 12 
 13 const int inf = 0x7f7f7f7f;
 14 
 15 struct Node {
 16     int lateAdd, Min, Data, cnt;
 17     bool Rev;
 18     Node *c[2], *p; // 0 for left child, while 1 for right child
 19 
 20     Node(int _Data = inf, int _cnt = 0) {
 21         Rev = false;
 22         Min = Data = _Data;
 23         lateAdd = 0;
 24         cnt = _cnt;
 25         c[0] = c[1] = p = NULL;
 26     }
 27 } *Null, *Root, *Head, *Tail;
 28 
 29 void up(Node *_x) {
 30     Node *nl = _x->c[0], *nr = _x->c[1];
 31 
 32     _x->Min = min(min(nl->Min, nr->Min), _x->Data);
 33     _x->cnt = nl->cnt + nr->cnt + 1;
 34 }
 35 
 36 void down(Node *_x) {
 37     Node *nl = _x->c[0], *nr = _x->c[1];
 38 
 39     if (_x->Rev) {
 40         if (nl != Null) {
 41             swap(nl->c[0], nl->c[1]);
 42             nl->Rev = !nl->Rev;
 43         }
 44         if (nr != Null) {
 45             swap(nr->c[0], nr->c[1]);
 46             nr->Rev = !nr->Rev;
 47         }
 48         _x->Rev = false;
 49     }
 50     if (_x->lateAdd) {
 51         int late = _x->lateAdd;
 52 
 53         if (nl != Null) {
 54             nl->Min += late;
 55             nl->Data += late;
 56             nl->lateAdd += late;
 57         }
 58         if (nr != Null) {
 59             nr->Min += late;
 60             nr->Data += late;
 61             nr->lateAdd += late;
 62         }
 63         _x->lateAdd = 0;
 64     }
 65 }
 66 
 67 void traverse(Node *rt) {
 68     if (rt == Null) {
 69         return ;
 70     }
 71     down(rt);
 72     printf("rt %d  p %d  ls %d  rs %d  data %d  min %d cnt %d\n", rt, rt->p, rt->c[0], rt->c[1], rt->Data, rt->Min, rt->cnt);
 73     traverse(rt->c[0]);
 74     traverse(rt->c[1]);
 75 }
 76 
 77 void in_tra(Node *rt) {
 78     if (rt == Null) {
 79         return ;
 80     }
 81     down(rt);
 82     in_tra(rt->c[0]);
 83     if (rt ->Data != inf) printf("%d ", rt->Data);
 84     in_tra(rt->c[1]);
 85     up(rt);
 86 }
 87 
 88 void Rotate(Node *_x, bool right) { // false for left rotate, while true for right rotate
 89     Node *_y = _x->p;
 90     bool left = !right;
 91 
 92     down(_y);
 93     down(_x);
 94     _y->c[left] = _x->c[right];
 95 
 96     if (_x->c[right] != Null) _x->c[right]->p = _y;
 97     _x->p = _y->p;
 98     if (_y->p != Null) {
 99         if (_y->p->c[0] == _y) {
100             _y->p->c[0] = _x;
101         } else {
102             _y->p->c[1] = _x;
103         }
104     }
105 
106     _x->c[right] = _y;
107     _y->p = _x;
108     if (_y == Root) Root = _x;
109 
110     up(_y);
111 }
112 
113 void Splay(Node *_x, Node *_f) {// splay _x to the node under _f
114     down(_x);
115     while (_x->p != _f) {
116         if (_x->p->p == _f) {
117             if (_x->p->c[0] == _x) {
118                 Rotate(_x, 1);
119             } else {
120                 Rotate(_x, 0);
121             }
122         } else {
123             Node *_y = _x->p, *_z = _y->p;
124 
125             if (_z->c[0] == _y) {
126                 if (_y->c[0] == _x) {
127                     Rotate(_y, 1);
128                     Rotate(_x, 1);
129                 } else {
130                     Rotate(_x, 0);
131                     Rotate(_x, 1);
132                 }
133             } else {
134                 if (_y->c[0] == _x) {
135                     Rotate(_x, 1);
136                     Rotate(_x, 0);
137                 } else {
138                     Rotate(_y, 0);
139                     Rotate(_x, 0);
140                 }
141             }
142         }
143     }
144 
145     up(_x);
146 }
147 
148 Node *getPos(int pos) {
149     Node *p = Root;
150 
151     // find position
152     pos++;
153     while (true) {
154         down(p);
155 
156         int cnt = p->c[0]->cnt;
157 
158         if (pos == cnt + 1) {
159             break;
160         } else if (pos <= cnt) {
161             p = p->c[0];
162         } else {
163             pos -= cnt + 1;
164             p = p->c[1];
165         }
166     }
167 
168     return p;
169 }
170 
171 void insPos(int elem, int pos) {
172     Node *pl = getPos(pos), *pr = getPos(pos + 1);
173     Node *tmp = new Node(elem, 1);
174 
175     // insert node
176     Splay(pl, Null);
177     Splay(pr, pl);
178     pr->c[0] = tmp;
179     tmp->p = pr;
180     tmp->c[0] = tmp->c[1] = Null;
181 
182     Splay(tmp, Null);
183 }
184 
185 void delPos(int pos) {
186     Node *pl = getPos(pos - 1), *pr = getPos(pos + 1);
187     Node *p;
188 
189     Splay(pl, Null);
190     Splay(pr, pl);
191     p = pr->c[0];
192     pr->c[0] = Null;
193 
194     delete p;
195     Splay(pr, Null);
196 }
197 
198 void init() {
199     Null = new Node();
200     Head = Root = new Node(inf, 2);
201     Tail = new Node(inf, 1);
202 
203     Root->c[1] = Tail;
204     Root->c[0] = Root->p = Null;
205     Tail->p = Root;
206     Tail->c[0] = Tail->c[1] = Null;
207 }
208 
209 void input(int n) {
210     int x;
211 
212     for (int i = 0; i < n; i++) {
213         scanf("%d", &x);
214         insPos(x, i);
215     }
216 }
217 
218 void reverse(int l, int r) {
219     if (l == r) return ;
220     Node *pl = getPos(l - 1), *pr = getPos(r + 1);
221 
222     // get segment
223     Splay(pl, Null);
224     Splay(pr, pl);
225 
226     pr = pr->c[0];
227     swap(pr->c[0], pr->c[1]);
228     pr->Rev = true;
229 
230     Splay(pr, Null);
231 }
232 
233 void revolve(int l, int r, int t) {
234     t %= (r - l + 1);
235     if (l == r || t == 0) return ;
236 
237     Node *pl = getPos(r - t), *pr = getPos(r + 1);
238 
239 //    printf("%d %d %d %d %d\n", pl, pr, l, r, t);
240 
241     // get segment
242     Splay(pl, Null);
243     Splay(pr, pl);
244 
245     // cut down segment
246     Node *tmp = pr->c[0];
247 
248     pr->c[0] = Null;
249     Splay(pr, Null);
250 
251     // insert segment
252     pl = getPos(l - 1);
253     pr = getPos(l);
254     Splay(pl, Null);
255     Splay(pr, pl);
256 
257     pr->c[0] = tmp;
258     tmp->p = pr;
259     Splay(tmp, Null);
260 }
261 
262 void add(int l, int r, int d) {
263     Node *pl = getPos(l - 1), *pr = getPos(r + 1);
264 
265 //    printf("%d %d   %d %d\n", pl, pr, l, r);
266     Splay(pl, Null);
267     Splay(pr, pl);
268 
269     pr = pr->c[0];
270     down(pr);
271     pr->lateAdd += d;
272     pr->Data += d;
273     pr->Min += d;
274     Splay(pr, Null);
275 }
276 
277 int getMin(int l, int r) {
278     Node *pl = getPos(l - 1), *pr = getPos(r + 1);
279 
280     Splay(pl, Null);
281     Splay(pr, pl);
282     pr = pr->c[0];
283     down(pr);
284 
285     return pr->Min;
286 }
287 
288 int main() {
289     int n;
290 //    int cnt = 0;
291 
292 //    freopen("in", "r", stdin);
293 //    freopen("out", "w", stdout);
294 
295     while (~scanf("%d", &n)) {
296 //        printf("cnt %d\n", ++cnt);
297         init();
298         input(n);
299 //        puts("Input success!");
300 //        puts("~~~");
301 //        traverse(Root);
302 //        puts("!!!");
303         scanf("%d", &n);
304 //        in_tra(Root);
305 //        printf("~~~cnt %d\n", Root->cnt - 2);
306         for (int i = 1; i <= n; i++) {
307             char buf[10];
308             int l, r, d ;
309 
310             scanf("%s", buf);
311             if (!strcmp(buf, "ADD")) {
312                 scanf("%d%d%d", &l, &r, &d);
313                 if (l > r) swap(l, r);
314                 add(l, r, d);
315             } else if (!strcmp(buf, "REVERSE")) {
316                 scanf("%d%d", &l, &r);
317                 if (l > r) swap(l, r);
318                 reverse(l, r);
319             } else if (!strcmp(buf, "REVOLVE")) {
320                 scanf("%d%d%d", &l, &r, &d);
321                 if (l > r) swap(l, r);
322                 revolve(l, r, d);
323             } else if (!strcmp(buf, "INSERT")) {
324                 scanf("%d%d", &l, &r);
325                 insPos(r, l);
326             } else if (!strcmp(buf, "DELETE")) {
327                 scanf("%d", &l);
328                 delPos(l);
329             } else {
330                 scanf("%d%d", &l, &r);
331                 if (l > r) swap(l, r);
332                 printf("%d\n", getMin(l, r));
333             }
334 
335 //            printf("op %d %s\n", i, buf);
336 //            in_tra(Root);
337 //            printf("~~~cnt %d\n", Root->cnt - 2);
338 
339 //            puts("~~~~~~~~~~~~~");
340 //            traverse(Root);
341 //            puts("!!!!!!!!!!!!!");
342         }
343     }
344 
345     return 0;
346 }
347 
348 #endif
349 
350 #if prog == 2
351 
352 #include <cstdio>
353 #include <cstring>
354 #include <algorithm>
355 
356 using namespace std;
357 
358 const int maxn = 10000;
359 int a[maxn], ttLen;
360 
361 void input(int n) {
362     ttLen = n;
363     for (int i = 1; i <= n; i++) {
364         scanf("%d", &a[i]);
365     }
366 }
367 
368 void add(int l, int r, int d) {
369     for (int i = l; i <= r; i++) {
370         a[i] += d;
371     }
372 }
373 
374 void revolve(int l, int r, int t) {
375     t %= (r - l + 1);
376     if (r == l || t == 0) return ;
377 
378     int buf[maxn];
379 
380     for (int i = l; i <= r; i++) {
381         buf[i - l] = a[i];
382     }
383     for (int i = 0; i <= r - l; i++) {
384         a[(i + t) % (r - l + 1) + l] = buf[i];
385     }
386 }
387 
388 void insPos(int elem, int pos) {
389     int p = ttLen;
390 
391     while (p > pos) {
392         a[p + 1] = a[p];
393         p--;
394     }
395     a[pos + 1] = elem;
396     ttLen++;
397 }
398 
399 void delPos(int pos) {
400     int p = pos;
401 
402     while (p < ttLen) {
403         a[p] = a[p + 1];
404         p++;
405     }
406     ttLen--;
407 }
408 
409 int getMin(int l, int r) {
410     int ret = 0x7f7f7f7f;
411 
412     for (int i = l; i <= r; i++) {
413         ret = min(ret, a[i]);
414     }
415 
416     return ret;
417 }
418 
419 int main() {
420     int n;
421 
422     freopen("in", "r", stdin);
423     freopen("cmp", "w", stdout);
424 
425     while (~scanf("%d", &n)) {
426         input(n);
427 
428         scanf("%d", &n);
429         for (int i = 1; i <= ttLen; i++) printf("%d ", a[i]);
430         printf("~~~cnt %d\n", ttLen);
431         for (int i = 1; i <= n; i++) {
432             char buf[10];
433             int l, r, d ;
434 
435             scanf("%s", buf);
436             if (!strcmp(buf, "ADD")) {
437                 scanf("%d%d%d", &l, &r, &d);
438                 if (l > r) swap(l, r);
439                 add(l, r, d);
440             } else if (!strcmp(buf, "REVERSE")) {
441                 scanf("%d%d", &l, &r);
442                 if (l > r) swap(l, r);
443                 reverse(a + l, a + r + 1);
444             } else if (!strcmp(buf, "REVOLVE")) {
445                 scanf("%d%d%d", &l, &r, &d);
446                 if (l > r) swap(l, r);
447                 revolve(l, r, d);
448             } else if (!strcmp(buf, "INSERT")) {
449                 scanf("%d%d", &l, &r);
450                 insPos(r, l);
451             } else if (!strcmp(buf, "DELETE")) {
452                 scanf("%d", &l);
453                 delPos(l);
454             } else {
455                 scanf("%d%d", &l, &r);
456                 if (l > r) swap(l, r);
457                 printf("%d\n", getMin(l, r));
458             }
459 
460 //            printf("op %d %s\n", i, buf);
461 //            for (int j = 1; j <= ttLen; j++) printf("%d ", a[j]);
462 //            printf("~~~cnt %d\n", ttLen);
463 
464         }
465     }
466 
467     return 0;
468 }
469 
470 #endif

  下面这是昨晚训练的一道题,刚开始的时候我直接就想到了Segment Tree,可是想到这题用Segment Tree解决的代码难度相对用Splay Tree会大不少,所以我就想到了用昨天懂的Splay Tree来完成,虽然中间出现一点小问题,不过最后还是1y通过了!

  题意是初始化一个1到n的序列,每个操作将删除指定的区间,并且返回区间两端最接近的未被删除的点的位置,如果没有就返回星号。用Splay Tree方便就是方便在删除区间的同时就找到了要输出的两个值。查找端点的时候,先找到最接近区间端点的值的结点,然后利用Splay操作,把该结点旋转至根,这样可以相当方便的找到前驱和后继。删除区间就是删除被夹逼出来的一个子树。这题给了一秒的时间,刚开始评估复杂度的时候因为Splay操作常数大,觉得可能会超时,结果不到500ms就得到结果了!

UVA 12356: uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3778

View Code
  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <stack>
  6 #include <vector>
  7 #include <cmath>
  8 
  9 using namespace std;
 10 int inf = 0x7f7f7f7f;
 11 
 12 struct Node {
 13     int key, cnt;
 14     int p, c[2];
 15 
 16     void init(int _key, int _cnt) {
 17         key = _key;
 18         cnt = _cnt;
 19         p = c[0] = c[1] = 0;
 20     }
 21 } node[100010];
 22 int Null, Root, cntNode;
 23 
 24 void up(int rt) {
 25     node[rt].cnt = node[node[rt].c[0]].cnt + node[node[rt].c[1]].cnt + 1;
 26 }
 27 
 28 void rotate(int x, bool right) {
 29     int y = node[x].p;
 30     bool left = !right;
 31 
 32     node[y].c[left] = node[x].c[right];
 33     if (node[x].c[right] != Null) node[node[x].c[right]].p = y;
 34     node[x].p = node[y].p;
 35     if (node[y].p != Null) {
 36         if (node[node[y].p].c[false] == y) node[node[y].p].c[false] = x;
 37         else node[node[y].p].c[true] = x;
 38     }
 39     node[x].c[right] = y;
 40     node[y].p = x;
 41 
 42     if (y == Root) Root = x;
 43     up(x);
 44 }
 45 
 46 void splay(int x, int f) {
 47     while (node[x].p != f) {
 48         if (node[node[x].p].p == f) {
 49             if (node[node[x].p].c[0] == x) {
 50                 rotate(x, true);
 51             } else {
 52                 rotate(x, false);
 53             }
 54         } else {
 55             int y = node[x].p, z = node[y].p;
 56 
 57             if (node[z].c[false] == y) {
 58                 if (node[y].c[false] == x) {
 59                     rotate(y, true);
 60                     rotate(x, true);
 61                 } else {
 62                     rotate(x, false);
 63                     rotate(x, true);
 64                 }
 65             } else {
 66                 if (node[y].c[false] == x) {
 67                     rotate(x, true);
 68                     rotate(x, false);
 69                 } else {
 70                     rotate(y, false);
 71                     rotate(x, false);
 72                 }
 73             }
 74         }
 75     }
 76     up(x);
 77 }
 78 
 79 void init() {
 80     Null = 0;
 81     node[Null].init(inf, 0);
 82     Root = cntNode = 1;
 83 
 84     node[Root].init(-inf, 1);
 85     cntNode++;
 86     node[Root].c[1] = cntNode;
 87     node[cntNode].init(inf, 1);
 88     node[cntNode].p = Root;
 89 }
 90 
 91 int find(int key, bool right) {
 92     int p = Root;
 93 
 94     while (true) {
 95         if (node[p].key == key) break;
 96         else if (node[p].key < key) {
 97             if (node[p].c[1] == Null) break;
 98             p = node[p].c[1];
 99         } else {
100             if (node[p].c[0] == Null) break;
101             p = node[p].c[0];
102         }
103     }
104     if (right) {
105         if (node[p].key <= key) {
106             splay(p, Null);
107             while (node[p].key <= key) p = node[p].c[1];
108             while (node[p].c[0] != Null && node[node[p].c[0]].key >= key) p = node[p].c[0];
109         }
110         return p;
111     } else {
112         if (node[p].key >= key) {
113             splay(p, Null);
114             while (node[p].key >= key) p = node[p].c[0];
115             while (node[p].c[1] != Null && node[node[p].c[1]].key <= key) p = node[p].c[1];
116         }
117         return p;
118     }
119 }
120 
121 void delSeg(int &l, int &r){
122     l = find(l, false);
123 //    puts("~~~");
124     r = find(r, true);
125 //    puts("!!!");
126 //    printf("%d %d\n", l, r);
127 //    printf("%d %d\n", node[l].key, node[r].key);
128     splay(l, Null);
129     splay(r, l);
130     node[r].c[0] = Null;
131 }
132 
133 void build(int n) {
134     init();
135     for (int i = 1; i <= n; i++) {
136         cntNode++;
137         node[cntNode].init(i, 1);
138         node[cntNode].c[1] = node[Root].c[1];
139         node[node[Root].c[1]].p = cntNode;
140         node[Root].c[1] = cntNode;
141         node[cntNode].p = Root;
142 
143         splay(cntNode, Null);
144     }
145 }
146 
147 void in_tra(int rt) {
148     if (rt == Null) return ;
149     in_tra(node[rt].c[0]);
150     printf("%d ", node[rt].key);
151     in_tra(node[rt].c[1]);
152 }
153 
154 int main() {
155 //    freopen("in", "r", stdin);
156 //    freopen("out", "w", stdout);
157 
158     int n, m;
159 
160     while (~scanf("%d%d", &n, &m) && (n + m)) {
161         build(n);
162         while (m--) {
163             int l, r;
164 
165             scanf("%d%d", &l, &r);
166             delSeg(l, r);
167             if (node[l].key == -inf) putchar('*');
168             else printf("%d", node[l].key);
169             putchar(' ');
170             if (node[r].key == inf) putchar('*');
171             else printf("%d", node[r].key);
172             puts("");
173         }
174         puts("-");
175     }
176 
177     return 0;
178 }

  下面这题也是是比较简单的,只用到了反转操作,不过数列不是一个单纯的排列,所以要先处理出稳定排序后的结果,重新附上标号以后就可以直接模拟了!

HDU 1890: acm.hdu.edu.cn/showproblem.php?pid=1890

View Code
  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <algorithm>
  5 
  6 using namespace std;
  7 
  8 const int inf = 0x7f7f7f7f;
  9 struct Node {
 10     int cnt;
 11     bool rev;
 12     Node *c[2], *p;
 13 
 14     Node(int _cnt = 0) {
 15         cnt = _cnt;
 16         rev = false;
 17         c[0] = c[1] = p = NULL;
 18     }
 19 } *Null, *Root;
 20 
 21 void up(Node *rt) {
 22     rt->cnt = rt->c[0]->cnt + rt->c[1]->cnt + 1;
 23 }
 24 
 25 void init() {
 26     Null = new Node();
 27     Root = new Node(1);
 28 
 29     Root->c[0] = Root->p = Null;
 30     Root->c[1] = new Node(1);
 31     Root->c[1]->p = Root;
 32     Root->c[1]->c[0] = Root->c[1]->c[1] = Null;
 33     up(Root);
 34 }
 35 
 36 void down(Node *rt) {
 37     Node *ls = rt->c[0], *rs = rt->c[1];
 38 
 39     if (rt->rev) {
 40         if (ls != Null) {
 41             swap(ls->c[0], ls->c[1]);
 42             ls->rev = !ls->rev;
 43         }
 44         if (rs != Null) {
 45             swap(rs->c[0], rs->c[1]);
 46             rs->rev = !rs->rev;
 47         }
 48         rt->rev = false;
 49     }
 50 }
 51 
 52 void rotate(Node *x, bool right) {
 53     Node *y = x->p;
 54     bool left = !right;
 55 
 56     down(y);
 57     down(x);
 58     y->c[left] = x->c[right];
 59     if (x->c[right] != Null) {
 60         x->c[right]->p = y;
 61     }
 62     x->p = y->p;
 63     if (y->p != Null) {
 64         if (y->p->c[0] == y) {
 65             y->p->c[0] = x;
 66         } else {
 67             y->p->c[1] = x;
 68         }
 69     }
 70     x->c[right] = y;
 71     y->p = x;
 72 
 73     up(y);
 74     if (y == Root) Root = x;
 75 }
 76 
 77 void splay(Node *x, Node *f) {
 78     down(x);
 79 
 80     while (x->p != f) {
 81         if (x->p->p == f) {
 82             if (x->p->c[0] == x) {
 83                 rotate(x, true);
 84             } else {
 85                 rotate(x, false);
 86             }
 87         } else {
 88             Node *y = x->p, *z = y->p;
 89 
 90             if (z->c[0] == y) {
 91                 if (y->c[0] == x) {
 92                     rotate(y, true);
 93                     rotate(x, true);
 94                 } else {
 95                     rotate(x, false);
 96                     rotate(x, true);
 97                 }
 98             } else {
 99                 if (y->c[0] == x) {
100                     rotate(x, true);
101                     rotate(x, false);
102                 } else {
103                     rotate(y, false);
104                     rotate(x, false);
105                 }
106             }
107         }
108     }
109 
110     up(x);
111 }
112 
113 const int maxn = 100005;
114 struct List {
115     int data;
116     int pri;
117 } list[maxn];
118 Node *rec[maxn];
119 
120 bool cmp1(List _a, List _b) {
121     if (_a.data != _b.data) return _a.data < _b.data;
122     return _a.pri < _b.pri;
123 }
124 
125 bool cmp2(List _a, List _b) {
126     return _a.pri < _b.pri;
127 }
128 
129 Node *getNode(int pos) {
130     Node *p = Root;
131 
132     pos++;
133     while (true) {
134         down(p);
135 
136         int c = p->c[0]->cnt;
137 
138         if (pos == c + 1) {
139             return p;
140         } else if (pos <= c) {
141             p = p->c[0];
142         } else {
143             pos -= c + 1;
144             p = p->c[1];
145         }
146     }
147 }
148 
149 void insPos(int data, int pos) {
150     Node *pl = getNode(pos), *pr = getNode(pos + 1);
151 
152     splay(pl, Null);
153     splay(pr, pl);
154 
155     Node *tmp = new Node(1);
156 
157     down(pr);
158     rec[data] = tmp;
159     pr->c[0] = tmp;
160     tmp->p = pr;
161     tmp->c[0] = tmp->c[1] = Null;
162 
163     splay(tmp, Null);
164 }
165 
166 int getPos(Node *x) {
167     splay(x, Null);
168 
169     return x->c[0]->cnt;
170 }
171 
172 void reverse(int n) {
173     Node *pl = getNode(n), *pr = getNode(getPos(rec[n]) + 1);
174 
175     if (pl->c[1] == rec[n]) return ;
176     splay(pl, Null);
177     splay(pr, pl);
178 
179     pr = pr->c[0];
180     down(pr);
181     pr->rev = !pr->rev;
182     swap(pr->c[0], pr->c[1]);
183 
184     splay(pr, Null);
185 }
186 
187 void in_tra(Node *rt) {
188     if (rt == Null) {
189         return ;
190     }
191     down(rt);
192     in_tra(rt->c[0]);
193     printf("%d %d %d p %d\n", rt, rt->c[0], rt->c[1], rt->p);
194     in_tra(rt->c[1]);
195 }
196 
197 void pre(int n) {
198     sort(list, list + n, cmp1);
199     for (int i = 0; i < n; i++) {
200         list[i].data = i;
201     }
202     sort(list, list + n, cmp2);
203     for (int i = 0; i < n; i++) {
204         insPos(list[i].data, i);
205     }
206 }
207 
208 void build(int n) {
209     init();
210     for (int i = 0, x; i < n; i++) {
211         scanf("%d", &x);
212         list[i].data = x;
213         list[i].pri = i;
214     }
215     pre(n);
216 }
217 
218 void deal(int n) {
219 //    in_tra(Root);
220 //    puts("~~~");
221 //    for (int i = 0; i < n; i++) {
222 //        printf("%d %d\n", i, rec[i]);
223 //    }
224 //    printf("%d\n", n);
225     for (int i = 0; i < n; i++) {
226         if (i) putchar(' ');
227         printf("%d", getPos(rec[i]));
228         reverse(i);
229     }
230     puts("");
231 }
232 
233 int main() {
234     int n;
235 
236 //    freopen("in", "r", stdin);
237 //    freopen("out", "w", stdout);
238     while (~scanf("%d", &n) && n) {
239         build(n);
240         deal(n);
241     }
242 
243     return 0;
244 }

  做这几题Splay Tree,暂时没遇到比较难的操作,不过Splay Tree的代码都有一定的长度的啊!如果没打好,debug起来是挺吃力的。。。囧!

  另外,除了中间那题,其余两题都是用动态内存处理的!

——written by Lyon

原文地址:https://www.cnblogs.com/LyonLys/p/poj_3580_UVA_12356_HDU_1890_Lyon.html