rt,贺的 oi wiki 的
# include <bits/stdc++.h>
# define int long long
# define rank charafrisk
using namespace std;
const double alpha = 0.7;
const int N = 1e5 + 5;
int nodecnt , root , w[N] , lc[N] , rc[N] , wn[N] , s[N] , sz[N] , sd[N] , n;
//节点个数
//,根
//,权值
//,左右儿子
//,某权值出现次数(wn[k]表示k号节点的元素出现几次)
//,子树大小(每个重复元素算1次)
//,子树大小(每个重复元素算wn[k]次)
//,考虑删除操作的子树大小。
int reb[N];
void calc (int now) {
s[now] = s[lc[now]] + s[rc[now]] + 1;
sz[now] = sz[lc[now]] + sz[rc[now]] + wn[now];
sd[now] = sd[lc[now]] + sd[rc[now]] + (wn[now] != 0);
}
bool CRebuild (int now) {
return wn[now] && (alpha * s[now] <= (double)max(s[lc[now]] , s[rc[now]])
|| (double)sd[now] <= alpha * s[now] ); }
void Reb_zk (int &cnt , int now) {
if (!now) return ;
Reb_zk (cnt , lc[now]);
if (wn[now]) reb[++cnt] = now;
Reb_zk (cnt , rc[now]);
}//展开
int Reb_build (int l , int r) {
int mid = l + r >> 1;
if (l >= r) return 0;
lc[reb[mid]] = Reb_build (l , mid);
rc[reb[mid]] = Reb_build (mid + 1 , r);
calc (reb[mid]);
return reb[mid];
}
void rebuild (int &now) {
int cnt = 0;
Reb_zk (cnt , now);
now = Reb_build (1 , cnt + 1); // 我他妈rebuild少建立一个节点
}
void Ins (int &now , int val) {
if (!now) {
now = ++nodecnt;
if (!root) root = 1;
w[now] = val , lc[now] = rc[now] = 0;
wn[now] = sz[now] = s[now] = sd[now] = 1;
}
else {
if (w[now] == val) wn[now] ++;
else if (w[now] < val) Ins (rc[now] , val);
else Ins (lc[now] , val);
calc (now);
if ( CRebuild(now) ) rebuild (now);
}
}
void Del (int & now , int val) {
if (!now) return ;
if (w[now] == val) if (wn[now]) -- wn[now];
else {
if (w[now] < val) Del (rc[now] , val);
else Del(lc[now] , val);
}
calc (now);
if ( CRebuild(now) ) rebuild (now);
}
int qry_rankpre (int now , int val) { //查有几个数比他小,就是查权值严格小于某值的最大名次
if (!now) return 0;
else if (w[now] == val && wn[now]) return sz[lc[now]];
else if (w[now] < val) return qry_rankpre (rc[now] , val) + sz[lc[now]] + wn[now];
else return qry_rankpre (lc[now] , val);
}
int qry_ranknxt (int now , int val) { //和上面的反着来,权值严格大于某值的最小名次。
if (!now) return 1;
if (w[now] == val && wn[now]) return sz[lc[now]];
else if (val < w[now]) return qry_ranknxt (lc[now] , val);
else return qry_ranknxt (rc[now] , val) + sz[lc[now]] + wn[now];
}
int qry_rankval (int now , int rk) {//查某个排名的数
if (!now) return 0;
else if (sz[lc[now]] < rk && rk <= sz[lc[now]] + wn[now]) return w[now];
else if (sz[lc[now]] + wn[now] < rk) return qry_rankval (rc[now] , rk - sz[lc[now]] - wn[now]);
else return qry_rankval (lc[now] , rk);
}
int Fdpre (int now , int val) { return qry_rankval (now , qry_rankpre(now , val) ); }
int Fdnxt (int now , int val) { return qry_rankval (now , qry_ranknxt(now , val) ); }
signed main () {
cin >> n;
while ( n -- ) {
int opt , x;
cin >> opt >> x;
if (opt == 1) Ins (root , x);
if (opt == 2) Del (root , x);
if (opt == 3) cout << qry_rankpre (root , x) + 1 << "\n" ;
if (opt == 4) cout << qry_rankval (root , x) << "\n";
if (opt == 5) cout << Fdpre (root , x) << "\n";
if (opt == 6) cout << Fdnxt (root , x) << "\n";
}
return 0;
}