#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define maxn 1000001
using namespace std;
int f[maxn],ch[maxn][2],num[maxn],cnt[maxn],size[maxn];
int tree_size,root,n,p,t,x;
inline void clear(int x){
ch[x][0]=ch[x][1]=f[x]=cnt[x]=num[x]=size[x]=0;
}//将这个节点全部清空,清空即将所有信息初始化为0
inline int get(int x){
return ch[f[x]][1]==x;
}//每次判断是在左儿子还是右儿子,并且巧妙地运用了。。。(ch[f[x]][1]==x返回值是1,那么就是右儿子!!!)
inline void update(int x){//更新子树的大小
if (x){
size[x]=cnt[x];
if (ch[x][0]) size[x]+=size[ch[x][0]];
if (ch[x][1]) size[x]+=size[ch[x][1]];
}
}
inline void rotate(int x){
int y=f[x];
int z=f[y];
int tmp=get(x);
ch[y][tmp]=ch[x][!tmp];//y在进行一次旋转之后必然会连接在(与原先接在z方向上不同的)的方向位置
f[ch[y][tmp]]=y;//将原先放置在与(y连接z相反方向)的tmp(即相反方向的儿子)连在y上(数学归纳法总结。。。。)
ch[x][!tmp]=y;
f[y]=x;
f[x]=z;
if (z) ch[z][ch[z][1]==y]=x;//如果其祖父节点是存在的话,那就将原来y的位置换为x的位置。。。。
update(y),update(x);//每次将子树的大小更新一次
}
inline void splay(int x){
for (int fa; (fa=f[x]); rotate(x))
if (f[fa]) rotate(((get(x)==get(fa))?fa:x));
root=x;
//每次执行的同时,判断是链式还是拐弯式的,并对其进行rotate操作。。。
}
inline void insert(int x){
if (root==0) {
tree_size++;
ch[tree_size][0]=ch[tree_size][1]=f[tree_size]=0;
root=tree_size;
size[tree_size]=cnt[tree_size]=1;
num[tree_size]=x;
return;
}
//还未开始建子树的判断
int now=root,father=0;
while (1){
if (x==num[now]){
cnt[now]++;
update(now);//更新当前节点信息
update(father);//由于当前节点的信息和父亲节点的信息是紧密相关的,所以需要更新父节点信息
splay(now);
break;//如果有重复现象,那么就将计数器++,并且将其再进行一次玄学伸展。。。
}
//如果没有重复。。。
father=now;
now=ch[now][num[now]<x];//如果没能找到其位置,就继续根据其权值的大小下放该数
if (now==0){//如果找不到子节点。。。那么就意味着已经找到了该值的归宿(有点怪)
tree_size++;//将它放置到树编号的最末
ch[tree_size][0]=ch[tree_size][1]=0;//初始化它的子节点
f[tree_size]=father;//并将其接到父节点上
size[tree_size]=cnt[tree_size]=1;//更新它所包含的子树大小以及计数值
ch[father][num[father]<x]=tree_size;//更新其父节点
num[tree_size]=x;
update(father);
splay(tree_size);
break;
}
}
}
inline int findx(int x){//查找序号为x的节点
int now=root;
while (1){
if (x<=size[ch[now][0]]) now=ch[now][0];//如果在左儿子,就转向左儿子
else{
int tmp=size[ch[now][0]]+cnt[now];//转向右儿子。。。
if(x<=tmp) return num[now];
x-=tmp; now=ch[now][1];
}
}
}
inline int find(int x){//查找值是x的序号
int now=root,ans=0;
while (1){
if (x<num[now]) now=ch[now][0];
else{
ans+=size[ch[now][0]];//累加树的节点个数
if (x==num[now]){
splay(now); return ans+1;
}
ans+=cnt[now];
now=ch[now][1];//向右扩展
}
}
}
inline int pre(){int now=ch[root][0]; while (ch[now][1]) now=ch[now][1]; return now;}
inline int next(){int now=ch[root][1]; while (ch[now][0]) now=ch[now][0]; return now;}
inline void del(int x){
find(x);//将x变为根节点!!
if (cnt[root]>1){ cnt[root]--; update(root); return;}//如果有重复直接一步更新
if (!ch[root][0] && !ch[root][1]) {clear(root); root=0; return;}//如果孤苦伶仃,就直接删除。。。
if (!ch[root][0]){
int y=root;
root=ch[root][1];
f[root]=0;//已经在根节点,所以f应赋成0
clear(y); return;
}
else if (!ch[root][1]){
int y=root;
root=ch[root][0];
f[root]=0;
clear(y);
return;
}
//将左边的最大移至根节点
int lef=pre(),y=root;
splay(lef);
ch[root][1]=ch[y][1];
f[ch[y][1]]=root;
clear(y);
update(root);
}
int main(){
scanf("%d",&n);
for (int i=1; i<=n; i++){
scanf("%d%d",&p,&x);
switch(p){
case 1:insert(x); break;
case 2:del(x); break;
case 3:printf("%d\n",find(x)); break;
case 4:printf("%d\n",findx(x)); break;
case 5:insert(x); printf("%d\n",num[pre()]); del(x); break;
case 6:{insert(x);
printf("%d\n",num[next()]);
del(x);
break;}
}}
}