Luogu P3369 【模板】普通平衡树 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138int root;int cntnd;int fa[MAXn + 10], son[MAXn + 10][2], hig[MAXn + 10];int val[MAXn + 10], cnt[MAXn + 10], siz[MAXn + 10];inline void pushup(int id) { hig[id] = max(hig[son[id][0]], hig[son[id][1]]) + 1; siz[id] = siz[son[id][0]] + siz[son[id][1]] + cnt[id];}inline int side(int id) { return son[fa[id]][1] == id;}inline void rotate(int id) { int y = fa[id], z = fa[y], sideid = side(id), s = son[id][sideid ^ 1]; if (z) {son[z][side(y)] = id;} fa[id] = z; son[y][sideid] = s; if (s) {fa[s] = y;} son[id][sideid ^ 1] = y; fa[y] = id; pushup(y); pushup(id);}inline void avl(int id) { if (abs(hig[son[id][0]] - hig[son[id][1]]) >= 2) { int b = hig[son[id][0]] < hig[son[id][1]], big = son[id][b]; if (hig[son[big][b]] < hig[son[big][b ^ 1]]) rotate(son[big][b ^ 1]); int nwrt = son[id][b]; rotate(nwrt); if (fa[nwrt] == 0) root = nwrt; }}int top, stk[MAXn + 10];void Insert(int v) { int id = root; top = 0; while (id) { stk[++top] = id; if (v < val[id]) id = son[id][0]; else if (v > val[id]) id = son[id][1]; else break; } if (id) { ++cnt[id]; while (top) pushup(stk[top--]); } else { ++cntnd; if (stk[top]) son[stk[top]][v > val[stk[top]]] = cntnd; else root = cntnd; fa[cntnd] = stk[top]; hig[cntnd] = 1; val[cntnd] = v; cnt[cntnd] = 1; siz[cntnd] = 1; while (top) { pushup(stk[top]); avl(stk[top]); --top; } }}void Delete(int v) { int id = root; top = 0; while (id) { stk[++top] = id; if (v < val[id]) id = son[id][0]; else if (v > val[id]) id = son[id][1]; else break; } if (id) { --cnt[id]; if (cnt[id]) { while (top) pushup(stk[top--]); } else { if (son[id][0] == 0 && son[id][1] == 0) { if (top) --top; if (stk[top]) son[stk[top]][val[id] > val[stk[top]]] = 0; else root = 0; } else if (son[id][0] == 0 || son[id][1] == 0) { if (top) --top; int s = son[id][son[id][0] == 0]; if (stk[top]) { son[stk[top]][val[id] > val[stk[top]]] = s; fa[s] = stk[top]; } else { root = s; fa[s] = 0; } } else { int pre = son[id][0]; while (pre) { stk[++top] = pre; pre = son[pre][1]; } pre = stk[top--]; val[id] = val[pre]; cnt[id] = cnt[pre]; son[stk[top]][stk[top] != id] = son[pre][0]; if (son[pre][0]) fa[son[pre][0]] = stk[top]; } while (top) { pushup(stk[top]); avl(stk[top]); --top; } } }}int ValtoRank(int v) { int id = root, ans = 1; while (id) { if (v < val[id]) { id = son[id][0]; } else if (v > val[id]) { ans += siz[son[id][0]] + cnt[id]; id = son[id][1]; } else { ans += siz[son[id][0]]; break; } } return ans;}int RanktoId(int rk) { int id = root; while (true) { if (rk <= siz[son[id][0]]) { id = son[id][0]; } else if (rk <= siz[son[id][0]] + cnt[id]) { return id; } else { rk -= siz[son[id][0]] + cnt[id]; id = son[id][1]; } }}int PreId(int v) { return RanktoId(ValtoRank(v) - 1);}int NexId(int v) { return RanktoId(ValtoRank(v + 1));}