zoukankan      html  css  js  c++  java
  • [BZOJ3196] [Tyvj1730] 二逼平衡树(线段树 套 Splay)

    传送门

    至少BZOJ过了,其他的直接弃。

    您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:

    1.查询k在区间内的排名

    2.查询区间内排名为k的值

    3.修改某一位值上的数值

    4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)

    5.查询k在区间内的后继(后继定义为大于x,且最小的数)

    最外层套一颗线段树,用来表示区间,线段树下面套个splay用来维护当前线段树节点的区间。

    对于第二问可以二分,看看哪个数的排名为 k。

    ——代码

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 #define root 1, 1, n
      5 #define lson now << 1, l, mid
      6 #define rson now << 1 | 1, mid + 1, r
      7 #define ls son[now][0]
      8 #define rs son[now][1]
      9 #define debug puts("**************");
     10 
     11 const int MAXN = 3500001, INF = 2147483647;
     12 
     13 int n, m, sz;
     14 int seq[MAXN], rt[MAXN];
     15 int f[MAXN], son[MAXN][2], cnt[MAXN], key[MAXN], size[MAXN];
     16 
     17 inline int read()
     18 {
     19     int f = 1, x = 0;
     20     char ch = getchar();
     21     for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
     22     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
     23     return x * f;
     24 }
     25 
     26 inline int max(int x, int y)
     27 {
     28     return x > y ? x : y;
     29 }
     30 
     31 inline int min(int x, int y)
     32 {
     33     return x < y ? x : y;
     34 }
     35 
     36 inline void Splay_clear(int now)
     37 {
     38     f[now] = cnt[now] = key[now] = size[now] = ls = rs = 0;
     39 }
     40 
     41 inline void Splay_update(int now)
     42 {
     43     if(now)
     44     {
     45         size[now] = cnt[now];
     46         if(ls) size[now] += size[ls];
     47         if(rs) size[now] += size[rs];
     48     }
     49 }
     50 
     51 inline int Splay_get(int x)
     52 {
     53     return son[f[x]][1] == x;
     54 }
     55 
     56 inline void Splay_rotate(int x)
     57 {
     58     int old = f[x], oldf = f[old], wh = Splay_get(x);
     59     
     60     son[old][wh] = son[x][wh ^ 1];
     61     f[son[old][wh]] = old;
     62     
     63     son[x][wh ^ 1] = old;
     64     f[old] = x;
     65     
     66     if(oldf) son[oldf][son[oldf][1] == old] = x;
     67     f[x] = oldf;
     68     
     69     Splay_update(old);
     70     Splay_update(x);
     71 }
     72 
     73 inline void Splay_splay(int x)
     74 {
     75     for(int fa; fa = f[x]; Splay_rotate(x))
     76         if(f[fa])
     77             Splay_rotate(Splay_get(x) ^ Splay_get(fa) ? x : fa);
     78 }
     79 
     80 inline void Splay_insert(int x, int k)
     81 {
     82     int now = rt[x], fa = 0;
     83     if(!rt[x])
     84     {
     85         rt[x] = ++sz;
     86         key[sz] = k;
     87         size[sz] = cnt[sz] = 1;
     88         return;
     89     }
     90     while(1)
     91     {
     92         if(k == key[now])
     93         {
     94             cnt[now]++;
     95             Splay_update(now);
     96             Splay_splay(now);
     97             rt[x] = now;
     98             return;
     99         }
    100         fa = now;
    101         now = son[now][k > key[now]];
    102         if(!now)
    103         {
    104             rt[x] = ++sz;
    105             f[sz] = fa;
    106             key[sz] = k;
    107             size[sz] = cnt[sz] = 1;
    108             son[fa][k > key[fa]] = sz;
    109             //Splay_update(fa);
    110             Splay_splay(sz);
    111             return;
    112         }
    113     }
    114 }
    115 
    116 inline int Splay_findrank(int x, int k)
    117 {
    118     int now = rt[x], ans = 0;
    119     while(1)
    120     {
    121         if(!now) return ans;
    122         if(key[now] == k) return ans + size[ls];
    123         else if(key[now] < k)
    124         {
    125             ans += cnt[now] + size[ls];
    126             now = rs;
    127         }
    128         else now = ls;
    129     }
    130 }
    131 
    132 inline int Splay_find(int x, int k)
    133 {
    134     int now = rt[x];
    135     while(1)
    136     {
    137         if(key[now] > k) now = ls;
    138         else if(key[now] < k) now = rs;
    139         else
    140         {
    141             rt[x] = now;
    142             Splay_splay(now);
    143             return now;
    144         }
    145     }
    146 }
    147 
    148 inline int Splay_pre(int x)
    149 {
    150     int now = son[rt[x]][0];
    151     while(rs) now = rs;
    152     return now;
    153 }
    154 
    155 inline int Splay_suc(int x)
    156 {
    157     int now = son[rt[x]][1];
    158     while(ls) now = ls;
    159     return now;
    160 }
    161 
    162 inline void Splay_del(int x)
    163 {
    164     int now = rt[x];
    165     if(cnt[now] > 1)
    166     {
    167         cnt[now]--;
    168         Splay_update(now);
    169         return;
    170     }
    171     if(!ls && !rs)
    172     {
    173         rt[x] = 0;
    174         Splay_clear(now);
    175         return;
    176     }
    177     if(!ls || !rs)
    178     {
    179         rt[x] = ls + rs;
    180         f[rt[x]] = 0;
    181         Splay_clear(now);
    182         return;
    183     }
    184     int pre = Splay_pre(x);
    185     Splay_splay(pre);
    186     rt[x] = pre;
    187     son[pre][1] = rs;
    188     f[rs] = pre;
    189     Splay_clear(now);
    190     Splay_update(pre);
    191 }
    192 
    193 inline int Splay_findpre(int x, int k)
    194 {
    195     int now = rt[x], ans = -INF;
    196     while(now)
    197     {
    198         if(key[now] < k)
    199         {
    200             ans = max(ans, key[now]);
    201             now = rs;
    202         }
    203         else now = ls;
    204     }
    205     return ans;
    206 }
    207 
    208 inline int Splay_findsuc(int x, int k)
    209 {
    210     int now = rt[x], ans = INF;
    211     while(now)
    212     {
    213         if(key[now] > k)
    214         {
    215             ans = min(ans, key[now]);
    216             now = ls;
    217         }
    218         else now = rs;
    219     }
    220     return ans;
    221 }
    222 
    223 inline void SegTree_insert(int x, int k, int now, int l, int r)
    224 {
    225     Splay_insert(now, k);
    226     if(l == r) return;
    227     int mid = (l + r) >> 1;
    228     if(x <= mid) SegTree_insert(x, k, lson);
    229     else SegTree_insert(x, k, rson);
    230 }
    231 
    232 inline int SegTree_askrank(int x, int y, int k, int now, int l, int r)
    233 {
    234     if(x <= l && r <= y) return Splay_findrank(now, k);
    235     if(l > y || r < x) return 0;
    236     int mid = (l + r) >> 1;
    237     return SegTree_askrank(x, y, k, lson) + SegTree_askrank(x, y, k, rson);
    238 }
    239 
    240 inline void SegTree_change(int x, int k, int now, int l, int r)
    241 {
    242     Splay_find(now, seq[x]);
    243     Splay_del(now);
    244     Splay_insert(now, k);
    245     if(l == r) return;
    246     int mid = (l + r) >> 1;
    247     if(x <= mid) SegTree_change(x, k, lson);
    248     else SegTree_change(x, k, rson);
    249 }
    250 
    251 inline int SegTree_findpre(int x, int y, int k, int now, int l, int r)
    252 {
    253     if(x <= l && r <= y) return Splay_findpre(now, k);
    254     if(l > y || r < x) return -INF;
    255     int mid = (l + r) >> 1;
    256     return max(SegTree_findpre(x, y, k, lson), SegTree_findpre(x, y, k, rson));
    257 }
    258 
    259 inline int SegTree_findsuc(int x, int y, int k, int now, int l, int r)
    260 {
    261     if(x <= l && r <= y) return Splay_findsuc(now, k);
    262     if(l > y || r < x) return INF;
    263     int mid = (l + r) >> 1;
    264     return min(SegTree_findsuc(x, y, k, lson), SegTree_findsuc(x, y, k, rson));
    265 }
    266 
    267 int main()
    268 {
    269     int i, opt, x, y, z, ans, h, t, mid, maxn = 0;
    270     n = read();
    271     m = read();
    272     for(i = 1; i <= n; i++) seq[i] = read(), maxn = max(maxn, seq[i]), SegTree_insert(i, seq[i], root);
    273     for(i = 1; i <= m; i++)
    274     {
    275         opt = read();
    276         switch(opt)
    277         {
    278             case 1:
    279             {
    280                 x = read();
    281                 y = read();
    282                 z = read();
    283                 printf("%d
    ", SegTree_askrank(x, y, z, root) + 1);
    284                 break;
    285             }
    286             case 2:
    287             {
    288                 x = read();
    289                 y = read();
    290                 z = read();
    291                 h = 0, t = maxn;
    292                 while(h <= t)
    293                 {
    294                     mid = (h + t) >> 1;
    295                     if(SegTree_askrank(x, y, mid, root) + 1 <= z) h = mid + 1;
    296                     else ans = mid, t = mid - 1;
    297                 }
    298                 printf("%d
    ", ans - 1);
    299                 break;
    300             }
    301             case 3:
    302             {
    303                 x = read();
    304                 z = read();
    305                 SegTree_change(x, z, root);
    306                 seq[x] = z;
    307                 maxn = max(maxn, z);
    308                 break;
    309             }
    310             case 4:
    311             {
    312                 x = read();
    313                 y = read();
    314                 z = read();
    315                 printf("%d
    ", SegTree_findpre(x, y, z, root));
    316                 break;
    317             }
    318             case 5:
    319             {
    320                 x = read();
    321                 y = read();
    322                 z = read();
    323                 printf("%d
    ", SegTree_findsuc(x, y, z, root));
    324                 break;
    325             }
    326         }
    327     }
    328     return 0;
    329 }
    View Code
  • 相关阅读:
    java后端工具积累
    Java基础面试题整理
    MySql常问面试题
    jvm及并发面试题
    中间件redis kafka面试题
    笔记
    解决Git操作报错
    view的state和drawable的state 源码分析
    flutter_6_动态化简介
    有关namespace 命名空间
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/6873415.html
Copyright © 2011-2022 走看看