// Splay
const int MAXN = 1e5 + 5;
struct Splay_Tree {
#define INF 0x3f3f3f3f
struct Splay_Node {
int son[2], val, cnt, size, fa;
#define lson tr[p].son[0]
#define rson tr[p].son[1]
Splay_Node() {}
Splay_Node(int Val, int Cnt, int Size, int Fa) {
val = Val;
cnt = Cnt;
size = Size;
fa = Fa;
}
} tr[MAXN];
int tot, root;
bool Ident(int p) { return tr[tr[p].fa].son[1] == p; }
int Get(int val, int fa) {
tr[++tot].fa = fa, tr[tot].cnt = tr[tot].size = 1, tr[tot].val = val;
return tot;
}
void Update(int p) { tr[p].size = tr[lson].size + tr[rson].size + tr[p].cnt; }
void Build() {
root = Get(-INF, 0);
tr[root].son[1] = Get(INF, root);
Update(root);
}
void Connect(int p, int fa, int flag) { tr[fa].son[flag] = p, tr[p].fa = fa; }
void Rotate(int p) {
int fa = tr[p].fa, grand = tr[fa].fa;
int flag1 = Ident(p), flag2 = Ident(fa);
Connect(p, grand, flag2);
Connect(tr[p].son[flag1 ^ 1], fa, flag1);
Connect(fa, p, flag1 ^ 1);
Update(fa);
Update(p);
}
void Splay(int p, int to) {
for (int fa = tr[p].fa; tr[p].fa != to; Rotate(p), fa = tr[p].fa)
if (tr[fa].fa != to)
Ident(p) == Ident(fa) ? Rotate(fa) : Rotate(p);
if (!to)
root = p;
}
int Find(int p, int val) {
if (!p)
return 0;
if (val == tr[p].val)
return p;
else if (val < tr[p].val)
return Find(lson, val);
return Find(rson, val);
}
void Insert(int &p, int val, int fa) {
if (!p)
Splay(p = Get(val, fa), 0);
else if (val == tr[p].val) {
++tr[p].cnt;
Splay(p, 0);
} else if (val < tr[p].val)
Insert(lson, val, p);
else
Insert(rson, val, p);
}
void Delete(int val) {
int p = Find(root, val);
if (!p)
return;
if (tr[p].cnt > 1) {
--tr[p].cnt;
Splay(p, 0);
Update(p);
return;
}
Splay(p, 0);
int l = lson, r = rson;
while (tr[l].son[1]) l = tr[l].son[1];
while (tr[r].son[0]) r = tr[r].son[0];
Splay(l, 0);
Splay(r, l);
tr[r].son[0] = 0;
Update(r);
Update(l);
}
int Get_Rank(int p, int val) {
if (!p)
return 0;
if (val == tr[p].val) {
int res = tr[lson].size + 1;
Splay(p, 0);
return res;
} else if (val < tr[p].val)
return Get_Rank(lson, val);
int res = tr[lson].size + tr[p].cnt;
return Get_Rank(rson, val) + res;
}
int Get_Val(int p, int rank) {
if (!p)
return INF;
if (tr[lson].size >= rank)
return Get_Val(lson, rank);
else if (tr[lson].size + tr[p].cnt >= rank) {
Splay(p, 0);
return tr[p].val;
}
return Get_Val(rson, rank - tr[lson].size - tr[p].cnt);
}
int Get_Pre(int val) {
int p = root, ret;
while (p) {
if (tr[p].val < val) {
ret = tr[p].val;
p = rson;
} else
p = lson;
}
Splay(root, 0);
return ret;
}
int Get_Next(int val) {
int p = root, ret;
while (p) {
if (tr[p].val > val) {
ret = tr[p].val;
p = lson;
} else
p = rson;
}
Splay(root, 0);
return ret;
}
#undef lson
#undef rson
} tree;