voidconnect(int u, int f, int p){ node[u].fa = f; node[f].ch[p] = u; }
旋转操作
分析咕咕咕
1 2 3 4 5 6 7 8 9 10 11
voidrotate(int x){ int y = node[x].fa; int r = node[y].fa; int rp = identify(y); int yp = identify(x); int b = node[x].ch[yp ^ 1]; connect(b, y, yp); connect(y, x, yp ^ 1); connect(x, r, rp); update(y), update(x); }
旋转需要保证:
平衡树的中序遍历不变(不能破坏BST的性质)
受影响的节点维护的信息依然正确有效
root必须指向旋转后的根节点
具体分析旋转步骤(假设需要旋转的节点为x,其父亲为y,以右旋为例):
将y的左儿子指向x的右儿子,且x的右儿子的父亲指向y
将x的右儿子指向y,且y的父亲指向x
如果原来的y还有父亲z,那么把z的某个儿子(原来y所在的儿子位置)指向x,且x的父亲指向z
1 2 3 4 5 6 7 8 9 10 11
voidrotate(int x){ int y = node[x].fa, z = node[y].fa, p = identify(x); node[y].ch[p] = node[x].ch[p ^ 1]; node[node[x].ch[p ^ 1]].fa = y; node[x].ch[p ^ 1] = y; node[y].fa = x; node[x].fa = z; if (z) node[z].ch[y == node[z].ch[1]] = x; update(y); update(x); }
voidinsert(int val){ if (root == 0) { node[++cnt].val = val; node[cnt].cnt++; root = cnt; update(root); return; } int cur = root, f = 0; while (1) { if (node[cur].val == val) { node[cur].cnt++; update(cur); update(f); splay(cur); break; } f = cur, cur = node[cur].ch[node[cur].val < k]; if (cur == 0) { node[++cnt].val = val; node[cnt].cnt++; node[cnt].fa = f; node[f].ch[node[f].val < k] = cnt; update(cnt); update(f); splay(cnt); break; } } }
查询x的排名
分析咕咕咕
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
intqueryid(int val){ int ans = 0, cur = root; while (1) { if (val < node[cur].val) cur = node[cur].ch[0]; else { ans += node[node[cur].ch[0]].sum; if (val == node[cur].val) { splay(cur); return ans + 1; } ans += node[cur].cnt; cur = node[cur].ch[1]; } } }
查询排名为k的数
分析咕咕咕
1 2 3 4 5 6 7 8 9 10 11
intqueryrid(int k){ int cur = root; while (1) { if (node[cur].ch[0] && k <= node[node[cur].ch[0]].sum) cur = node[cur].ch[0]; else { k -= node[cur].cnt + node[node[cur].ch[0]].sum; if (k <= 0) return node[cur].val; cur = node[cur].ch[1]; } } }
查询前驱
分析古古古
1 2 3 4 5 6 7
intquerypre(int val){ insert(val); int cur = node[root].ch[0]; while (node[cur].ch[1]) cur = node[cur].ch[1]; delet(val); return cur; }
查询后继
1 2 3 4 5 6 7
intquerynxt(int val){ insert(val); int cur = node[root].ch[1]; while (node[cur].ch[0]) cur = node[cur].ch[0]; delet(val); return cur; }