题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3224
平衡树入门题,学习学习。
splay(学习yyb巨佬)
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 500100; 5 const int INF = 1e9; 6 inline void read(int &n) { 7 register int x = 0, t = 1; 8 register char ch = getchar(); 9 while (ch != '-' && (ch<'0' || ch>'9'))ch = getchar(); 10 if (ch == '-') { t = -1; ch = getchar(); } 11 while (ch >= '0'&&ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); } 12 n = x * t; 13 } 14 int root, len; 15 struct node { 16 int fa;//节点的父节点 17 int siz;//节点的子树数量 18 int ch[2];//节点的左(0)子节点和右(1)子节点 19 int val;//节点的值 20 int num;//节点的值的数量 21 }a[maxn]; 22 inline void pushup(int x) {//更新当前节点的子树//当前子树的大小是左子树大小加上右子树大小当前当前节点个数 23 a[x].siz = a[a[x].ch[0]].siz + a[a[x].ch[1]].siz + a[x].num; 24 } 25 inline void rotate(int x) {//旋转操作//将x旋转到x的父亲的位置 26 int y = a[x].fa;//y是x的父节点 27 int z = a[y].fa;//z是x的祖父节点 28 int k = (a[y].ch[1] == x);//求x是y的左(0)还是右(1)节点 29 a[z].ch[a[z].ch[1] == y] = x;//求y是z的左(0)还是右(1)节点,同时将x放在该位置 30 a[x].fa = z;//修改x的父节点 31 a[y].ch[k] = a[x].ch[k ^ 1];//把x的儿子给y 32 a[a[x].ch[k ^ 1]].fa = y;//更新父节点为y 33 a[x].ch[k ^ 1] = y;//y变为x的子节点 34 a[y].fa = x;//y的父亲更新为x 35 pushup(y), pushup(x);//更新y和x的子节点数量 36 } 37 inline void splay(int x, int goal) {//将x旋转为goal的子节点 38 while (a[x].fa != goal) { 39 int y = a[x].fa; 40 int z = a[y].fa; 41 if (z != goal) 42 (a[y].ch[1] == x) ^ (a[z].ch[1] == y) ? rotate(x) : rotate(y); 43 //如果x和y同为左儿子或者右儿子先旋转y 44 //如果x和y不同为左儿子或者右儿子先旋转x 45 //如果不双旋的话,旋转完成之后树的结构不会变化 46 rotate(x); 47 } 48 if (goal == 0) 49 root = x; 50 } 51 inline void insert(int x) { 52 int now = root, fa = 0;//当前节点now和now的父节点fa 53 while (now&&a[now].val != x) {//当now存在并且没有移动到当前的值 54 fa = now;//父节点变为now 55 now = a[now].ch[x > a[now].val];//x大于当前位置则now向右,否则now向左 56 } 57 if (now)//这个值出现过 58 a[now].num++;//值增加 59 else {//这个值第一次出现,要新建一个节点来存放 60 now = ++len; 61 if (fa)//父节点不是根节点(0) 62 a[fa].ch[x > a[fa].val] = now; 63 //初始化节点 64 a[now].ch[0] = a[now].ch[1] = 0; 65 a[now].siz = 1; 66 a[now].num = 1; 67 a[now].fa = fa; 68 a[now].val = x; 69 } 70 splay(now, 0); 71 } 72 inline void Find(int x) {//查找x的位置,并将其旋转到根节点 73 int now = root; 74 if (!now)return;//数为空 75 while (a[now].ch[x > a[now].val] && x != a[now].val)////当存在儿子并且当前位置的值不等于x 76 now = a[now].ch[x > a[now].val]; 77 splay(now, 0);//把当前位置旋转到根节点 78 } 79 inline int Next(int x, int flag) {//查找x的前驱(0)或者后继(1) 80 Find(x); 81 int now = root; 82 if (a[now].val > x&&flag)return now;//如果当前节点的值大于x并且要查找的是后继 83 if (a[now].val < x && !flag)return now;//如果当前节点的值小于x并且要查找的是前驱 84 now = a[now].ch[flag];//查找后继的话在右儿子上找,前驱在左儿子上找 85 while (a[now].ch[flag ^ 1])now = a[now].ch[flag ^ 1]; 86 return now; 87 } 88 inline void Delete(int x) {//删除一个x 89 int last = Next(x, 0);//查找x的前驱 90 int next = Next(x, 1);//查找x的后继 91 splay(last, 0), splay(next, last); 92 //将前驱旋转到根节点,后继旋转到根节点下面 93 //很明显,此时后继是前驱的右儿子,x是后继的左儿子,并且x是叶子节点 94 int now = a[next].ch[0];//后继的左儿子,也就是x 95 if (a[now].num > 1) {//超过一个就删除一个 96 a[now].num--; 97 splay(now, 0); 98 } 99 else 100 a[next].ch[0] = 0;//直接删除 101 102 } 103 inline int kth(int k) {//查找第k小的数 104 int now = root; 105 if (a[now].siz < k) 106 return 0; 107 while (1) { 108 int y = a[now].ch[0];//y是左儿子 109 if (k > a[y].siz + a[now].num) {//如果排名比左儿子的大小和当前节点的数量要大 110 k -= a[y].siz + a[now].num;//排名减小 111 now = a[now].ch[1];//定在右儿子上找 112 } 113 else { 114 if (k <= a[y].siz) 115 now = y; 116 else 117 return a[now].val; 118 } 119 } 120 } 121 int main() { 122 int n; 123 read(n); 124 root = 0, len = 0; 125 insert(1000000000); 126 insert(-1000000000); 127 while (n--) { 128 int q, x; 129 read(q), read(x); 130 if (q == 1) 131 insert(x); 132 else if (q == 2) 133 Delete(x); 134 else if (q == 3) { 135 Find(x); 136 printf("%d ", a[a[root].ch[0]].siz); 137 } 138 else if (q == 4) 139 printf("%d ", kth(x + 1)); 140 else if (q == 5) 141 printf("%d ", a[Next(x, 0)].val); 142 else if (q == 6) 143 printf("%d ", a[Next(x, 1)].val); 144 } 145 }
无旋Treap(学习fzszkl巨佬)
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1e5 + 10; 5 int Siz[maxn], ls[maxn], rs[maxn], val[maxn], pos[maxn], root; 6 int cnt; 7 int send = 19260817; 8 inline int Rand() { 9 send ^= send << 7; 10 send ^= send >> 5; 11 send ^= send << 13; 12 return send; 13 } 14 inline int New(int x) { 15 cnt++; 16 pos[cnt] = Rand(); 17 Siz[cnt] = 1; 18 val[cnt] = x; 19 return cnt; 20 } 21 inline void up(int x) { 22 Siz[x] = Siz[ls[x]] + Siz[rs[x]] + 1; 23 } 24 void split_size(int x, int siz, int &A, int &B) { 25 if (x == 0)return (void)(A = B = 0); 26 if (siz <= Siz[ls[x]]) 27 B = x, split_size(ls[x], siz, A, ls[x]); 28 else 29 A = x, split_size(rs[x], siz - Siz[ls[x]] - 1, rs[x], B); 30 up(x); 31 } 32 void split_val(int x, int v, int &A, int &B) { 33 if (x == 0)return (void)(A = B = 0); 34 if (v < val[x]) 35 B = x, split_val(ls[x], v, A, ls[x]); 36 else 37 A = x, split_val(rs[x], v, rs[x], B); 38 up(x); 39 } 40 int Merge(int A, int B) { 41 if (A == 0 || B == 0)return A | B; 42 int ans; 43 if (pos[A] > pos[B])ans = A, rs[A] = Merge(rs[A], B); 44 else ans = B, ls[B] = Merge(A, ls[B]); 45 up(ans); 46 return ans; 47 } 48 void dfs(int x) { 49 if (x == 0) 50 return; 51 printf("%d ", x); 52 dfs(ls[x]); 53 dfs(rs[x]); 54 } 55 void insert(int x) { 56 int A, B; 57 split_val(root, x - 1, A, B); 58 root = Merge(Merge(A, New(x)), B); 59 } 60 void Delete(int x) { 61 int A, B, C, D; 62 split_val(root, x - 1, A, B); 63 split_size(B, 1, C, D);//C就是删除的节点 64 root = Merge(A, D); 65 } 66 int Rank(int x) {//查x的排名 67 int A, B, ans; 68 split_val(root, x - 1, A, B); 69 ans = Siz[A] + 1; 70 root = Merge(A, B); 71 return ans; 72 } 73 int getR(int x) {//查第x名是什么 74 int A, B, C, D, ans; 75 split_size(root, x - 1, A, B); 76 split_size(B, 1, C, D); 77 ans = val[C]; 78 Merge(Merge(A, C), D); 79 return ans; 80 } 81 int last(int x) { 82 int A, B, C, D, ans; 83 split_val(root, x - 1, A, B); 84 split_size(A, Siz[A] - 1, C, D); 85 ans = val[D]; 86 Merge(Merge(C, D), B); 87 return ans; 88 } 89 int Next(int x) { 90 int A, B, C, D, Ans; 91 split_val(root, x, A, B); 92 split_size(B, 1, C, D); 93 Ans = val[C]; 94 root = Merge(Merge(A, C), D); 95 return Ans; 96 } 97 int main() { 98 int n; 99 scanf("%d", &n); 100 while (n--) { 101 int opt, x; 102 scanf("%d%d", &opt, &x); 103 if (opt == 1) 104 insert(x); 105 else if (opt == 2) 106 Delete(x); 107 else if (opt == 3) 108 printf("%d ", Rank(x)); 109 else if (opt == 4) 110 printf("%d ", getR(x)); 111 else if (opt == 5) 112 printf("%d ", last(x)); 113 else if (opt == 6) 114 printf("%d ", Next(x)); 115 } 116 return 0; 117 }