//平衡树 替罪羊树
//不进行旋转 当左右子树重量相差过大(通常以3:1为界)就把树拍扁重构
//重构即以最中心节点为根节点 二分建树
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define lim 0.75//拍扁重构的标准
using namespace std;
int n,root,size,cnt;
int goat,flat[1000001];//需要拍扁重构的节点,拍扁重构时暂存的数组
struct uio{
int son[2],val,siz,ava;//左右儿子,权值,子树大小+自己大小,未被删除的子树大小
bool exist;//标记是否被删除
}scg[1000001];
bool check(int now)//判断是否拍扁
{
if((double)scg[now].ava*lim<=(double)max(scg[scg[now].son[0]].ava,scg[scg[now].son[1]].ava))
//这是说 如果此节点未被删除的节点总数的3/4比任意一棵子树未被删除的节点数少(即:一棵子树未被删除的节点数是另一棵的3倍还多)
return true;//需要拍扁
return false;//不用拍扁
}
void dfs(int now)//中序遍历,找出需要参与重构的节点
{
if(!now)
return;
dfs(scg[now].son[0]);
if(scg[now].exist)
flat[++cnt]=now;
dfs(scg[now].son[1]);
}
void build(int l,int r,int &now)//构造过程
{
int mid=(l+r)/2;
now=flat[mid];
if(l==r)
{
scg[now].son[0]=scg[now].son[1]=0;
scg[now].siz=scg[now].ava=1;
return;
}
if(l<mid)
build(l,mid-1,scg[now].son[0]);
else scg[now].son[0]=0;
build(mid+1,r,scg[now].son[1]);
scg[now].siz=scg[scg[now].son[0]].siz+scg[scg[now].son[1]].siz+1;
scg[now].ava=scg[scg[now].son[0]].ava+scg[scg[now].son[1]].ava+1;
}
void rebuild(int &now)//重构
{
cnt=0;
dfs(now);
if(cnt)
build(1,cnt,now);
else now=0;
}
int get_no(int k)
{
int now=root,ans=1;
while(now)
{
if(scg[now].val>=k)
now=scg[now].son[0];
else
{
ans+=scg[scg[now].son[0]].ava+scg[now].exist;
now=scg[now].son[1];
}
}
return ans;
}
void insert(int &now,int k)
{
if(!now)
{
now=++size;
scg[now].val=k;
scg[now].siz=scg[now].ava=1;
scg[now].exist=true;
scg[now].son[0]=scg[now].son[1]=0;
return;
}
scg[now].siz++;
scg[now].ava++;
if(scg[now].val>=k)
insert(scg[now].son[0],k);
else insert(scg[now].son[1],k);
if(!check(now))//此节点不需要重构
{//注:此处大括号不可去除!!!否则100行else会对应92行if而不是90行if导致多次拍扁重构!
if(goat)//子节点中有满足重构条件的点
{
if(scg[now].son[0]==goat)
rebuild(scg[now].son[0]);
else rebuild(scg[now].son[1]);
goat=0;
}
}//注:此处大括号不可去除!!!否则100行else会对应92行if而不是90行if导致多次拍扁重构!
else goat=now;//此节点需要重构,则继续记录
}
void del_pos(int &now,int k)
{
if(scg[now].exist&&scg[scg[now].son[0]].ava+1==k)
{
scg[now].exist=false;
scg[now].ava--;
return;
}
scg[now].ava--;
if(scg[scg[now].son[0]].ava+scg[now].exist>=k)
del_pos(scg[now].son[0],k);
else del_pos(scg[now].son[1],k-scg[scg[now].son[0]].ava-scg[now].exist);
}
void del_val(int k)
{
del_pos(root,get_no(k));
if((double)scg[root].siz*lim>=scg[root].ava)//若根节点被删除的节点过多(即:超过总结点的1/4)
rebuild(root);//重构根节点
}
int get_num(int k)
{
int now=root;
while(now)
{
if(scg[now].exist&&scg[scg[now].son[0]].ava+1==k)
return scg[now].val;
else if(scg[scg[now].son[0]].ava>=k)
now=scg[now].son[0];
else
{
k-=scg[scg[now].son[0]].ava+scg[now].exist;
now=scg[now].son[1];
}
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
if(u==1)
insert(root,v);
if(u==2)
del_val(v);
if(u==3)
printf("%d\n",get_no(v));
if(u==4)
printf("%d\n",get_num(v));
if(u==5)
printf("%d\n",get_num(get_no(v)-1));
//前驱:即k的位置的前一位
if(u==6)
printf("%d\n",get_num(get_no(v+1)));
//后继:即比k大的第一个数的位置 不能直接加一是因为k可能不止一个
}
return 0;
}