zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    操作系统丶并发并行和线程
    网络基础补充,断点续传,以及如何添加进度条
    python小游戏之贪吃蛇
    python2和3的区别丶网络编程以及socketserver多线程
    面向对象之套接字(socket)和黏包
    面向对象多继承和网络编程
    约束,自定义异常,加密,日志
    方法和函数,isinstance/issubclass/type以及反射
    面向对象之组合的补充,主动调用其他类的成员,特殊成员
    关于卡尔曼滤波和粒子滤波最直白的解释
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6061827.html
Copyright © 2011-2022 走看看