//Treap fhq版(不旋转)
//所有操作依靠split()(分离)和merge()(合并)完成
//可支持区间操作和可持久化 比普通Treap更通用
//所有Treap中序遍历均为递增序列
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<ctime>
using namespace std;
int n,cnt,size,root,x,y,z;
//x为小Treap的根节点 y为中Treap的根节点 z为大Treap的根节点 root为总Treap的根节点
int son[100001][2],siz[100001],val[100001],rd[100001];
//左右儿子,子树大小+自己大小,点值,随机权值
int new_node(int m)//建立新节点
{
siz[++size]=1;
val[size]=m;
rd[size]=rand();
return size;
}
void update(int now)
{
siz[now]=siz[son[now][0]]+siz[son[now][1]]+1;
}
void split(int now,int k,int &a,int &b)
{
if(!now)
{
a=b=0;
return;
}
if(val[now]<=k)
a=now,split(son[now][1],k,son[now][1],b);
//将此节点及其左子树接到小Treap上,并遍历此节点的右节点
else b=now,split(son[now][0],k,a,son[now][0]);
//将此节点及其右子树接到大Treap上,并遍历此节点的左节点
update(now);
}
int merge(int a,int b)
{
if(!a||!b)
return a+b;
if(rd[a]<rd[b])
{
son[a][1]=merge(son[a][1],b);
//将小Treap节点及其左子树接在总Treap上,并遍历此节点的右节点
update(a);
return a;
}
else
{
son[b][0]=merge(a,son[b][0]);
//将大Treap节点及其右子树接在总Treap上,并遍历此节点的左节点
update(b);
return b;
}
}
int k_th(int now,int k)
{
while(1)
{
if(k<=siz[son[now][0]])
now=son[now][0];
else if(k==siz[son[now][0]]+1)
return now;
else
{
k-=siz[son[now][0]]+1;
now=son[now][1];
}
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int u,k;
scanf("%d%d",&u,&k);
if(u==1)//插入
{
split(root,k,x,z);//先分成两个Treap 此时k(若有)在小Treap中
root=merge(merge(x,new_node(k)),z);//重新合并
}
if(u==2)//删除
{
split(root,k,x,z);//先分成两个Treap 此时k在小Treap中
split(x,k-1,x,y);//再把小Treap分成两个Treap 此时k在中Treap中 且为中Treap根节点
y=merge(son[y][0],son[y][1]);//把中Treap根节点的两个子树合并 此时已删除k
root=merge(merge(x,y),z);//重新合并
}
if(u==3)//查找权值为k的排名
{
split(root,k-1,x,z);//先分成两个Treap 此时小Treap中包含了所有小于k的数
printf("%d\n",siz[x]+1);//k的排名即为小于k的权值数目+1
root=merge(x,z);//重新合并
}
if(u==4)//查找排名为k的权值
printf("%d\n",val[k_th(root,k)]);//直接输出
if(u==5)//求前驱
{
split(root,k-1,x,z);//先分成两个Treap 此时k是大Treap中最小的数
printf("%d\n",val[k_th(x,siz[x])]);//前驱即为小Treap中最大的数 即最右节点
root=merge(x,z);//重新合并
}
if(u==6)//求后继
{
split(root,k,x,z);//先分成两个Treap 此时k是小Treap中最大的数
printf("%d\n",val[k_th(z,1)]);//后继即为大Treap中最小的数 即最左节点
root=merge(x,z);//重新合并
}
}
return 0;
}