浅谈平衡树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
原文地址:https://www.cnblogs.com/shl-blog/p/11138926.html