• 浅谈平衡树Treap


    Description

    Treap是一种简单的平衡树,可以实现插入元素,删除元素,求元素的排名,求排名为某某的元素,查询前驱后驱

    treap的本质是一棵二叉搜索树。然而,二叉搜索树很容易使复杂度退化,所以我们在每个节点上产生一个随机值,按照堆的性质维护,这样treap的深度期望为logn。

    在本题中,我们在每一个节点上维护以下域:左儿子,右儿子,子树大小,随机权值(维护堆),储存的权值,相同权值的个数。

    那么我们就可以仿照BST的写法,写出Treap的一部分(略)

    Treap的精髓在于,能通过旋转,使得树平衡。具体地,我们有左旋和右旋两种操作,能维护平衡树

    以右旋为例,假设原来x是y的左儿子,A和B是x的左右子树,那么右旋之后,x成了y的父亲,y成了x的右儿子,B成为了y的左子树。

    左旋类似

    这样我们在BST的基础上就得到了Treap

    code

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 inline int read() {
      5     int ret = 0, op = 1;
      6     char c = getchar();
      7     while (c < '0' || c > '9') {
      8         if (c == '-') op = -1; 
      9         c = getchar();
     10     }
     11     while (c <= '9' && c >= '0') {
     12         ret = ret * 10 + c - '0';
     13         c = getchar();
     14     }
     15     return ret * op;
     16 }
     17 const int INF = 2147483647;
     18 int n, root, tot;
     19 struct treap {
     20     int l, r;
     21     int size, cnt, rnd, val;
     22 } a[100010];
     23 int New(int val) {
     24     a[++tot].val = val;
     25     a[tot].rnd = rand();
     26     a[tot].size = a[tot].cnt = 1;
     27     return tot;
     28 }
     29 void update(int now) {
     30     a[now].size = a[a[now].l].size + a[a[now].r].size + a[now].cnt;
     31 }
     32 void build() {
     33     root = New(-INF);
     34     a[root].r = New(INF);
     35     update(root);
     36 }
     37 void zig(int &now) {
     38     int q = a[now].l;
     39     a[now].l = a[q].r;
     40     a[q].r = now;
     41     now = q;
     42     update(a[now].r);
     43     update(now);
     44 }
     45 void zag(int &now) {
     46     int q = a[now].r;
     47     a[now].r = a[q].l;
     48     a[q].l = now;
     49     now = q;
     50     update(a[now].l);
     51     update(now);
     52 }
     53 void insert(int &now, int val) {
     54     if (!now) {
     55         now = New(val);
     56         return ;
     57     }
     58     if (a[now].val == val) {
     59         a[now].cnt++;
     60         update(now);
     61         return ;
     62     }
     63     if (val < a[now].val) {
     64         insert(a[now].l, val);
     65         if (a[a[now].l].rnd > a[now].rnd) zig(now);
     66     }
     67     else {
     68         insert(a[now].r, val);
     69         if (a[a[now].r].rnd > a[now].rnd) zag(now);
     70     }
     71     update(now);
     72 }
     73 void del(int &now, int val) {
     74     if (!now) return ;
     75     if (a[now].val == val) {
     76         if (a[now].cnt > 1) {
     77             a[now].cnt--;
     78             update(now);
     79             return ;
     80         }
     81         if (a[now].l || a[now].r) {
     82             if (!a[now].r || a[a[now].l].rnd > a[a[now].r].rnd) {
     83                 zig(now); del(a[now].r, val);
     84             }
     85             else {
     86                 zag(now); del(a[now].l, val);
     87             }
     88             update(now);
     89         }
     90         else now = 0;
     91         return ;
     92     }
     93     val < a[now].val ? del(a[now].l, val) : del(a[now].r, val);
     94     update(now);
     95 }
     96 int retrank(int now, int val) {
     97     if (!now) return 0;
     98     if (val == a[now].val) return a[a[now].l].size + 1;
     99     if (val < a[now].val) return retrank(a[now].l, val);
    100     return retrank(a[now].r, val) + a[a[now].l].size + a[now].cnt;
    101 }
    102 int retval(int now, int rank) {
    103     if (!now) return INF;
    104     if (a[a[now].l].size >= rank) return retval(a[now].l, rank);
    105     if (a[a[now].l].size + a[now].cnt >= rank) return a[now].val;
    106     return retval(a[now].r, rank - a[a[now].l].size - a[now].cnt);
    107 }
    108 int retpre(int val) {
    109     int now = root; 
    110     int ans;
    111     while (now) {
    112         if (a[now].val < val) {ans = a[now].val; now = a[now].r;}
    113         else now = a[now].l;
    114     }
    115     return ans;
    116 }
    117 int retnxt(int val) {
    118     int now = root;
    119     int ans;
    120     while (now) {
    121         if (a[now].val > val) {ans = a[now].val; now = a[now].l;}
    122         else now = a[now].r;
    123     }
    124     return ans;
    125 }
    126 int main() {
    127     srand((unsigned)time(NULL));
    128     build();
    129     n = read();
    130     while (n--) {
    131         int op = read(), x = read();
    132         if (op == 1) insert(root, x);
    133         else if (op == 2) del(root, x);
    134         else if (op == 3) printf("%d
    ", retrank(root, x) - 1);
    135         else if (op == 4) printf("%d
    ", retval(root, x + 1));
    136         else if (op == 5) printf("%d
    ", retpre(x));
    137         else printf("%d
    ", retnxt(x));
    138     }
    139     return 0;
    140 }
    Treap
  • 相关阅读:
    mybatis(1.2)
    Could not find resource mybatis.xml 找不到mybatis主配置文件的三种解决方式
    mybatis(1)
    linux笔记(一)
    javaScript(笔记1)
    过滤器 防止用户恶意登陆
    用户注册调优 及Connection对象
    请求转发的实现及其优缺点
    重定向的实现及其优缺点
    http状态码
  • 原文地址:https://www.cnblogs.com/shl-blog/p/11138926.html
Copyright © 2020-2023  润新知