期望平衡,即弱平衡

背景知识

1. 二叉搜索树BST

BST

2. 堆Heap

Heap

操作

  1. 插入
  2. 删除
  3. 找前驱/后继
  4. 找最大/最小
  5. 求某个值的排名
  6. 求排名是k的数是哪个
  7. 找比某个数小的最大值
  8. 找比某个数大的最小值

结构定义

  1. Node {
  2. int l, r;
  3. // key指二叉搜索树中的值,val指堆中的值(随机值),两个同时满足要求
  4. int key, val;
  5. }

这样就能唯一确定一个二叉搜索树。

插入

  1. 直接插入至叶节点,赋随机值val
  2. 旋转操作(左旋zag/右旋zig),类似于堆的pushup

删除

  1. 找到目标节点
  2. 通过不断左旋或右旋降低节点高度直至叶节点
  3. 删除目标节点

模板

AcWing 253. 普通平衡树

  1. // 省略IO
  2. public class Main {
  3. static IntReader in;
  4. static FastWriter out;
  5. static String INPUT = "";
  6. static class Node {
  7. int l, r;
  8. int key, val;
  9. int cnt, size;
  10. }
  11. static final int INF = (int)(1e8), N = 100010;
  12. static Node[] tr = new Node[N];
  13. static int n, idx;
  14. static Random random = new Random();
  15. static void solve() {
  16. n = ni();
  17. int root = build();
  18. for (int i = 1; i <= n; i++) {
  19. int op = ni(), x = ni();
  20. if (op == 1)
  21. root = insert(root, x);
  22. else if (op == 2)
  23. root = delete(root, x);
  24. else if (op == 3)
  25. out.println(getRank(root, x) - 1);
  26. else if (op == 4)
  27. out.println(getKey(root, x + 1));
  28. else if (op == 5)
  29. out.println(getPrev(root, x));
  30. else if (op == 6)
  31. out.println(getNext(root, x));
  32. }
  33. }
  34. static int getNext(int u, int x) {
  35. if (u == 0) return INF;
  36. if (tr[u].key <= x)
  37. return getNext(tr[u].r, x);
  38. else
  39. return Math.min(tr[u].key, getNext(tr[u].l, x));
  40. }
  41. static int getPrev(int u, int x) {
  42. if (u == 0) return -INF;
  43. if (tr[u].key >= x)
  44. return getPrev(tr[u].l, x);
  45. else
  46. return Math.max(tr[u].key, getPrev(tr[u].r, x));
  47. }
  48. static int getKey(int u, int rank) {
  49. if (u == 0) return 0;
  50. if (tr[tr[u].l].size >= rank)
  51. return getKey(tr[u].l, rank);
  52. else if (tr[tr[u].l].size + tr[u].cnt >= rank)
  53. return tr[u].key;
  54. else
  55. return getKey(tr[u].r, rank - tr[u].cnt - tr[tr[u].l].size);
  56. }
  57. static int getRank(int u, int key) {
  58. if (u == 0) return 0;
  59. if (tr[u].key == key) {
  60. return tr[tr[u].l].size + 1;
  61. } else if (tr[u].key > key) {
  62. return getRank(tr[u].l, key);
  63. } else {
  64. return tr[tr[u].l].size + tr[u].cnt + getRank(tr[u].r, key);
  65. }
  66. }
  67. static int delete(int u, int key) {
  68. if (u == 0) {
  69. return 0;
  70. }
  71. if (tr[u].key == key) {
  72. if (tr[u].cnt > 1)
  73. tr[u].cnt--;
  74. else if (tr[u].l != 0 || tr[u].r != 0) {
  75. if (tr[u].r == 0 || tr[u].l != 0 && tr[tr[u].l].val > tr[tr[u].r].val) {
  76. u = zig(u);
  77. tr[u].r = delete(tr[u].r, key);
  78. } else {
  79. u = zag(u);
  80. tr[u].l = delete(tr[u].l, key);
  81. }
  82. } else return 0;
  83. } else if (tr[u].key > key) {
  84. tr[u].l = delete(tr[u].l, key);
  85. } else {
  86. tr[u].r = delete(tr[u].r, key);
  87. }
  88. pushup(u);
  89. return u;
  90. }
  91. static int insert(int u, int key) {
  92. if (u == 0) {
  93. int p = createNode(key);
  94. return p;
  95. }
  96. if (tr[u].key == key) {
  97. tr[u].cnt++;
  98. } else if (tr[u].key > key) {
  99. tr[u].l = insert(tr[u].l, key);
  100. if (tr[u].val < tr[tr[u].l].val)
  101. u = zig(u);
  102. } else {
  103. tr[u].r = insert(tr[u].r, key);
  104. if (tr[u].val < tr[tr[u].r].val)
  105. u = zag(u);
  106. }
  107. pushup(u);
  108. return u;
  109. }
  110. static void pushup(int u) {
  111. tr[u].size = tr[tr[u].l].size + tr[tr[u].r].size + tr[u].cnt;
  112. }
  113. static int zag(int u) {
  114. int right = tr[u].r;
  115. tr[u].r = tr[right].l;
  116. tr[right].l = u;
  117. pushup(u);
  118. pushup(right);
  119. return right;
  120. }
  121. static int zig(int u) {
  122. int left = tr[u].l;
  123. tr[u].l = tr[left].r;
  124. tr[left].r = u;
  125. pushup(u);
  126. pushup(left);
  127. return left;
  128. }
  129. static int build() {
  130. tr[0] = new Node();
  131. int root = createNode(-INF), right = createNode(INF);
  132. tr[root].r = right;
  133. pushup(root);
  134. if (tr[root].val < tr[right].val)
  135. root = zag(root);
  136. return root;
  137. }
  138. static int createNode(int x) {
  139. ++idx;
  140. tr[idx] = new Node();
  141. tr[idx].key = x;
  142. tr[idx].val = random.nextInt(2 * INF) + 1;
  143. tr[idx].size = tr[idx].cnt = 1;
  144. return idx;
  145. }
  146. public static void main(String[] args) throws Exception {
  147. in = INPUT.isEmpty() ? new IntReader(System.in) : new IntReader(new ByteArrayInputStream(INPUT.getBytes()));
  148. out = new FastWriter(System.out);
  149. solve();
  150. out.flush();
  151. }
  152. }