structSplay { int s[2]; // 0 for left son, 1 for right son int p; // Father node index int dat; // Value int cnt; // Duplication count int size; // Node count in total } tree[N];
voidrotate(int x){ int y = tree[x].p, z = tree[y].p; // Father and grandfather int sn_pos = (tree[y].s[1] == x); // Where the son is, 0 left, 1 right int fa_pos = (tree[z].s[1] == y); // Where the father is, 0 left, 1 right tree[z].s[fa_pos] = x; // Son and father need a swap. If father was on the left previously, the son will be placed as a father on the left tree[x].p = z; // Update father 1 tree[y].s[sn_pos] = tree[x].s[sn_pos ^ 1]; // In the mid-traversal order, node B is between X and Y, so it will be linked to the opposite side tree[tree[x].s[sn_pos ^ 1]].p = y; // Update father 2 tree[x].s[sn_pos ^ 1] = y; // After a round of zigzagging, left branch that connects father and son will be switched to the right side tree[y].p = x; // Update father 3 update(y); update(x); }
voidsplay(int x, int k){ while (tree[x].p != k) { int y = tree[x].p, z = tree[y].p; // Father and grandfather int sn_pos = (tree[y].s[1] == x); // Son direction int fa_pos = (tree[z].s[1] == y); // Father direction if (z != k) { // More than one rotation to go if (sn_pos == fa_pos) rotate(y); // Linear elserotate(x); // Broken-linear } rotate(x); // Anyhow X needs a rotation } if (!k) root = x; // Upgrade as the new root }
voidinsert(int dat){ int u = root, p = 0; while (u) { p = u; if (tree[p].dat > dat) u = tree[u].s[0]; elseif (tree[p].dat < dat) u = tree[u].s[1]; else { tree[u].cnt++; splay(p); return; } } u = allocate(dat, p); if (p) { // Not first run if (tree[p].dat > dat) tree[p].s[0] = u; else tree[p].s[1] = u; } splay(u); }
voidinsertInterval(int pos, int tot){ int l = getIdxByRank(root, pos + 1); int r = getIdxByRank(root, pos + 2); splay(l); splay(r, l); int rt = build(0, tot - 1, r); tree[r].s[0] = rt; update(r); update(l); }
voidremoveNode(int idx, int dat){ int pre = precursor(dat); int suc = successor(dat); splay(pre); splay(suc, pre); int tar = tree[suc].s[0]; if (tree[tar].cnt > 1) { tree[tar].cnt--; splay(tar); } else tree[suc].s[0] = 0; }
voidremoveInterval(int pos, int tot){ int l = getIdxByRank(root, pos); int r = getIdxByRank(root, pos + tot + 1); splay(l); splay(r, l); gc(tree[r].s[0]); tree[r].s[0] = 0; update(r); update(l); }
有关排名查询和数值查询的内容与平衡树相同,故直接给出。注意
操作不要写到开头去了。
1 2 3 4 5 6 7 8 9 10 11 12
intgetRankByData(int idx, int dat){ if (!idx) return1; if (tree[idx].dat > dat) returngetRankByData(tree[idx].s[0], dat) + 1; returngetRankByData(tree[idx].s[1], dat) + (tree[idx].s[0] ? leftSubtree(idx).size : 0) + tree[idx].cnt; }
intgetDataByRank(int idx, int rank){ if (!idx) return -INF; if (leftSubtree(idx).size >= rank) returngetDataByRank(tree[idx].s[0], rank); if (leftSubtree(idx).size + tree[idx].cnt >= rank) return tree[idx].dat; returngetDataByRank(tree[idx].s[1], rank - (tree[idx].s[0] ? leftSubtree(idx).size : 0) - tree[idx].cnt); }