Description
Treap是一种简单的平衡树,可以实现插入元素,删除元素,求元素的排名,求排名为某某的元素,查询前驱后驱
treap的本质是一棵二叉搜索树。然而,二叉搜索树很容易使复杂度退化,所以我们在每个节点上产生一个随机值,按照堆的性质维护,这样treap的深度期望为logn。
在本题中,我们在每一个节点上维护以下域:左儿子,右儿子,子树大小,随机权值(维护堆),储存的权值,相同权值的个数。
那么我们就可以仿照BST的写法,写出Treap的一部分(略)
Treap的精髓在于,能通过旋转,使得树平衡。具体地,我们有左旋和右旋两种操作,能维护平衡树
以右旋为例,假设原来x是y的左儿子,A和B是x的左右子树,那么右旋之后,x成了y的父亲,y成了x的右儿子,B成为了y的左子树。
左旋类似
这样我们在BST的基础上就得到了Treap
code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }