平衡树
平衡树
1、可以维护一个数在数组中的排名,排名为 \(x\) 的数,一个数的前驱和后驱。
3、查询和修改的时间复杂度:\(O(logn)\)。
template<typename T>
struct Splay{
struct node{
int fa;
int cnt;
int siz;
T val;
int ch[2];
node(int fa = 0, int cnt = 0, int siz = 0, T val = T{})
: fa(fa), cnt(cnt), siz(siz), val(val) {
ch[0] = ch[1] = 0;
}
#define fa_(x) tree[x].fa
#define cnt_(x) tree[x].cnt
#define siz_(x) tree[x].siz
#define val_(x) tree[x].val
#define c0_(x) tree[x].ch[0]
#define c1_(x) tree[x].ch[1]
};
int root = 0, tot = 0;
vector<node> tree;
Splay() {
tree.push_back(node());
}
inline void maintain(int x) {
siz_(x) = siz_(c0_(x)) + siz_(c1_(x)) + cnt_(x);
}
inline bool get(int x) {
return x == c1_(fa_(x));
}
inline void clear(int x) {
tree[x] = node();
}
inline void rotate(int x) {
int y = fa_(x), z = fa_(y), chk = get(x);
if (chk) c1_(y) = c0_(x), (c0_(x) ? fa_(c0_(x)) = y : 0), c0_(x) = y;
else c0_(y) = c1_(x), (c1_(x) ? fa_(c1_(x)) = y : 0), c1_(x) = y;
fa_(y) = x;
fa_(x) = z;
if (z) (y == c0_(z) ? c0_(z) = x : c1_(z) = x);
maintain(y);
maintain(x);
}
inline void splay(int x) {
for (int f = fa_(x); f = fa_(x), f; rotate(x))
if (fa_(f)) rotate(get(x) == get(f) ? f : x);
root = x;
}
inline void ins(T val) {
if (!root) {
root = ++tot;
tree.push_back(node(0, 1, 1, val));
return;
}
int cur = root, f = 0;
while (1) {
if (val_(cur) == val) {
cnt_(cur)++;
maintain(cur);
maintain(f);
splay(cur);
break;
}
f = cur;
cur = val_(cur) > val ? c0_(cur) : c1_(cur);
if (!cur) {
++tot;
tree.push_back(node(f, 1, 1, val));
val < val_(f) ? c0_(f) = tot : c1_(f) = tot;
maintain(cur);
maintain(f);
splay(tot);
break;
}
}
}
inline int rhk(T val) {
int res = 0, cur = root;
while (1) {
if (val < val_(cur)) {
cur = c0_(cur);
} else {
res += siz_(c0_(cur));
if (val == val_(cur)) {
splay(cur);
return res + 1;
}
res += cnt_(cur);
cur = c1_(cur);
}
}
}
inline T kth(int x) {
int cur = root;
while (1) {
if (c0_(cur) && x <= siz_(c0_(cur))) {
cur = c0_(cur);
} else {
x -= siz_(c0_(cur)) + cnt_(cur);
if (x <= 0) {
splay(cur);
return val_(cur);
}
cur = c1_(cur);
}
}
}
inline int pre_() {
int cur = c0_(root);
if (!cur) return cur;
while (c1_(cur)) cur = c1_(cur);
splay(cur);
return cur;
}
inline int nxt() {
int cur = c1_(root);
if (!cur) return cur;
while (c0_(cur)) cur = c0_(cur);
splay(cur);
return cur;
}
inline void del(int val) {
rhk(val);
if (cnt_(root) > 1) {
cnt_(root)--;
maintain(root);
return;
}
if (!c0_(root) && !c1_(root)) {
clear(root);
root = 0;
return;
}
if (!c0_(root)) {
int cur = root;
root = c1_(root);
fa_(root) = 0;
clear(cur);
return;
}
if (!c1_(root)) {
int cur = root;
root = c0_(root);
fa_(root) = 0;
clear(cur);
return;
}
int cur = root, x = pre_();
fa_(c1_(cur)) = x;
c1_(x) = c1_(cur);
clear(cur);
maintain(root);
}
};
void solve() {
int q;
read(q);
Splay<int> t;
while (q--) {
int opt, x;
read(opt, x);
if (opt == 1) {
t.ins(x);
} else if (opt == 2) {
t.del(x);
} else if (opt == 3) {
t.ins(x);
printf("%d\n", t.rhk(x));
t.del(x);
} else if (opt == 4) {
printf("%d\n", t.kth(x));
} else if (opt == 5) {
t.ins(x);
printf("%d\n", t.val_(t.pre_()));
t.del(x);
} else {
t.ins(x);
printf("%d\n", t.val_(t.nxt()));
t.del(x);
}
}
}

浙公网安备 33010602011771号