// Fhq-Treap
const int MAXN = 1e5 + 5;
struct Fhq_Treap {
struct Fhq_Node {
int l, r, val, key, size;
#define lson tr[p].l
#define rson tr[p].r
Fhq_Node() {}
Fhq_Node(int L, int R, int Val, int Key, int Size) {
l = L;
r = R;
val = Val;
key = Key;
size = Size;
}
} tr[MAXN];
int tot = 0, root = 0;
int Get(int val) {
tr[++tot] = Fhq_Treap(0, 0, val, rand(), 1);
return tot;
}
void Push_Up(int p) { tr[p].size = tr[lson].size + tr[rson].size + 1; }
void Split(int p, int val, int &x, int &y) {
if (!p) {
x = 0, y = 0;
return;
}
if (tr[p].val <= val) {
x = p;
Split(rson, val, rson, y);
} else {
y = p;
Split(lson, val, x, lson);
}
Push_Up(p);
}
int Merge(int x, int y) {
if (!x || !y)
return x + y;
if (tr[x].key <= tr[y].key) {
tr[x].r = Merge(tr[x].r, y);
Push_Up(x);
return x;
} else {
tr[y].l = Merge(x, tr[y].l);
Push_Up(y);
return y;
}
}
void Insert(int val) {
int x, y;
Split(root, val, x, y);
root = Merge(Merge(x, Get(val)), y);
}
void Delete(int val) {
int x, y, z;
Split(root, val, x, z);
Split(x, val - 1, x, y);
y = Merge(tr[y].l, tr[y].r);
root = Merge(Merge(x, y), z);
}
int Get_Rank(int val) {
int x, y, ret;
Split(root, val - 1, x, y);
ret = tr[x].size + 1;
root = Merge(x, y);
return ret;
}
int Get_Val(int Rank) {
int p = root;
while (p) {
if (tr[lson].size + 1 == Rank)
return tr[p].val;
else if (Rank <= tr[lson].size)
p = lson;
else {
Rank -= (tr[lson].size + 1);
p = rson;
}
}
return 0;
}
int Get_Pre(int val) {
int x, y, p;
Split(root, val - 1, x, y);
p = x;
while (rson) p = rson;
root = Merge(x, y);
return tr[p].val;
}
int Get_Next(int val) {
int x, y, p;
Split(root, val, x, y);
p = y;
while (lson) p = lson;
root = Merge(x, y);
return tr[p].val;
}
} tree;