template <typename T>
class Treap {
private:
struct node {
T val;
int pri, siz, cnt;
node *l, *r;
node() {
l = r = nullptr;
siz = cnt = 0;
}
node(T v) {
l = r = nullptr;
val = v, pri = rand();
siz = cnt = 1;
}
};
node *root;
private:
inline void maintain(node *u) {
u->siz = u->cnt;
if (u->l != nullptr) u->siz += u->l->siz;
if (u->r != nullptr) u->siz += u->r->siz;
}
private:
pair<node *, node *> split(node *u, T val) {
if (u == nullptr) return make_pair(nullptr, nullptr);
if (val < u->val) {
auto v = split(u->l, val);
u->l = v.second;
maintain(u);
return make_pair(v.first, u);
} else {
auto v = split(u->r, val);
u->r = v.first;
maintain(u);
return make_pair(u, v.second);
}
}
private:
node *merge(node *u, node *v) {
if (u == nullptr) return v;
if (v == nullptr) return u;
if (u->pri < v->pri) {
v->l = merge(u, v->l);
maintain(v);
return v;
} else {
u->r = merge(u->r, v);
maintain(u);
return u;
}
}
private:
node *find(node *u, T val) {
if (u == nullptr) return nullptr;
if (u->val == val) return u;
if (val < u->val) return find(u->l, val);
return find(u->r, val);
}
private:
node *pre(node *u, T val) {
if (u == nullptr) return nullptr;
if (val > u->val) {
auto ret = pre(u->r, val);
if (ret == nullptr) ret = u;
return ret;
}
return pre(u->l, val);
}
private:
node *sub(node *u, T val) {
if (u == nullptr) return nullptr;
if (val < u->val) {
auto ret = sub(u->l, val);
if (ret == nullptr) ret = u;
return ret;
}
return sub(u->r, val);
}
private:
node *num(node *u, int rnk) {
int sz = 0;
if (u->l != nullptr) sz = u->l->siz;
if (rnk >= sz + 1 && rnk <= sz + u->cnt) return u;
if (rnk <= sz) return num(u->l, rnk);
return num(u->r, rnk - sz - u->cnt);
}
private:
int rnk(node *u, T val) {
// count from 1
if (u == nullptr) return 1;
int sz = 0;
if (u->l != nullptr) sz = u->l->siz;
if (val == u->val) return sz + 1;
if (val < u->val) return rnk(u->l, val);
return sz + u->cnt + rnk(u->r, val);
}
private:
void _upd(node *u, T val) {
if (u == nullptr || u->val == val) return;
if (val < u->val)
_upd(u->l, val);
else
_upd(u->r, val);
maintain(u);
}
public:
node *insert(T val) {
auto ret = find(root, val);
if (ret != nullptr) {
ret->cnt++, ret->siz++;
_upd(root, val);
return ret;
}
ret = new node(val);
auto v = split(root, val);
root = merge(merge(v.first, ret), v.second);
return ret;
}
public:
bool del(T val) {
auto v = find(root, val);
if (v == nullptr) return false;
if (v->cnt > 1) {
v->cnt--, v->siz--;
_upd(root, val);
} else {
auto o = split(root, val - 1);
auto p = split(o.second, val);
delete p.first;
root = merge(o.first, p.second);
}
return true;
}
public:
int rnk(T val) { return rnk(root, val); }
public:
T num(int rnk) { return num(root, rnk)->val; }
public:
T pre(T val) { return pre(root, val)->val; }
public:
T sub(T val) { return sub(root, val)->val; }
};