二叉平衡树
1 # include<iostream>
2 # include<stdio.h>
3 # include<algorithm>
4 # include<string>
5 using namespace std;
6 /*建树的过程和二叉树大差不差*/
7 const int N = 100010, INF = 1e8;
8
9 int n;
10 struct node {
11 int l, r;
12 int key, val;
13 int cnt, size;
14 } tr[N];
15
16 int root, idx;
17
18 void pushup(int p) {
19 tr[p].size = tr[tr[p].l].size + tr[tr[p].r].size + tr[p].cnt;
20 }/*用子树的数据来维护父节点的数据*/
21
22 int get_node(int key) {
23 tr[++idx].key = key;
24 tr[idx].val = rand();
25 tr[idx].cnt = tr[idx].size = 1;
26 return idx;
27 }
28
29 void zig(int &p) { /*右旋*/
30 int q = tr[p].l;
31 tr[p].l = tr[q].r;
32 tr[q].r = p;
33 p = q;
34 pushup(tr[p].r), pushup(p);
35 }
36
37 void zag(int &p) { /*左旋*/
38 int q = tr[p].r;
39 tr[p].r = tr[q].l;
40 tr[q].l = p;
41 p = q;
42 pushup(tr[p].l), pushup(p);
43 }
44
45 void build() {
46 get_node(-INF), get_node(INF);
47 root = 1;
48 tr[1].r = 2;
49 pushup(root);
50 if (tr[1].val < tr[2].val) zag(root);
51 }
52
53 void insert(int &p, int key) {
54 if (!p) p = get_node(key);
55 else if (tr[p].key == key) tr[p].cnt++;
56 else if (tr[p].key > key) {
57 insert(tr[p].l, key);
58 if (tr[tr[p].l].val > tr[p].val) zig(p);
59 } else {
60 insert(tr[p].r, key);
61 if (tr[tr[p].r].val > tr[p].val) zag(p);
62 }
63 pushup(p);
64 }
65
66 void remove(int &p, int key) {
67 if (!p) return;
68 if (tr[p].key == key) {
69 if (tr[p].cnt > 1)
70 tr[p].cnt--;
71 else if (tr[p].l || tr[p].r) {
72 if (!tr[p].r || tr[tr[p].l].val > tr[tr[p].r].val) {
73 zig(p);
74 remove(tr[p].r, key);
75 } else {
76 zag(p);
77 remove(tr[p].l, key);
78 }
79 } else p = 0;
80 } else if (tr[p].key > key) remove(tr[p].l, key);
81 else remove(tr[p].r, key);
82 pushup(p);
83 }
84
85 int get_rank_by_key(int p, int key) {
86 if (!p) return 0;
87 if (tr[p].key == key) return tr[tr[p].l].size + 1;
88 if (tr[p].key > key) return get_rank_by_key(tr[p].l, key);
89 return tr[tr[p].l].size + tr[p].cnt + get_rank_by_key(tr[p].r, key);
90 }
91
92 int get_key_by_rank(int p, int rank) {
93 if (!p) return INF;
94 if (tr[tr[p].l].size >= rank) return get_key_by_rank(tr[p].l, rank);
95 if (tr[tr[p].l].size + tr[p].cnt >= rank) return tr[p].key;
96 return get_key_by_rank(tr[p].r, rank - tr[tr[p].l].size - tr[p].cnt);
97 }
98
99 int get_prev(int p, int key) {
100 if (!p) return -INF;
101 if (tr[p].key >= key) return get_prev(tr[p].l, key);
102 return max(tr[p].key, get_prev(tr[p].r, key));
103 }
104
105 int get_next(int p, int key) {
106 if (!p) return INF;
107 if (tr[p].key <= key) return get_next(tr[p].r, key);
108 return min(tr[p].key, get_next(tr[p].l, key));
109 }
110
111 int main() {
112 build();
113
114 scanf("%d", &n);
115 while (n--) {
116 int op, x;
117 scanf("%d%d", &op, &x);
118 if (op == 1) insert(root, x);
119 else if (op == 2) remove(root, x);
120 else if (op == 3) printf("%d\n", get_rank_by_key(root, x) - 1);
121 else if (op == 4) printf("%d\n", get_key_by_rank(root, x + 1));
122 else if (op == 5) printf("%d\n", get_prev(root, x));
123 else printf("%d\n", get_next(root, x));
124 }
125
126
127
128 return 0;
129 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】