Splay
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+1e5;
struct splay{
int fa,ch[2],val,cnt,siz;
}t[maxn];
int root,tot,xx,n,opt,m;
inline void update(int x){//更新子树大小
t[x].siz=t[t[x].ch[0]].siz+t[t[x].ch[1]].siz+t[x].cnt;
}
inline void rotate(int x){//旋转,交换该节点及其父亲节点的位置并维护平衡树性质 左旋拎右左挂右,右旋拎左右挂左
int y=t[x].fa;//x的父亲
int z=t[y].fa;//x的爷爷
int k=t[y].ch[1]==x;//x相对y的位置,0为左儿子,1为右儿子
t[z].ch[t[z].ch[1]==y]=x;//把z的y儿子所处位置变为x
t[x].fa=z;//x父亲变为z
t[y].ch[k]=t[x].ch[k^1];// 原x所在y的位置更新为不与y在同一链上的x的儿子
t[t[x].ch[k^1]].fa=y;
t[x].ch[k^1]=y;//y成为x与原位置关系相反的儿子
t[y].fa=x;
update(y);//更新
update(x);
}
inline void splay(int x,int king){//伸展,将x转到king节点的左或右儿子上
while(t[x].fa!=king){//转到x成为king的儿子
int y=t[x].fa,z=t[y].fa;
if(z!=king){//祖父非king
if((t[z].ch[0]==y)^(t[y].ch[0]==x)) rotate(x);//父亲和祖父方向不一致,+line32共转自己两次
else rotate(y);//父亲祖父方向一致,+line32先转父亲再转祖父
//等效(t[z].ch[0]==y)^(t[y].ch[0]==x)?rotate(x):rotate(y);
}
rotate(x);//祖父是king只转自己一次,或同上
}
if(king==0) root=x;//如果king是0,将根节点赋值为x
}
inline void find(int x){//找元素并转到根节点
int u=root;
if(!u) return;//树是空的
while(t[u].ch[x>t[u].val]&&x!=t[u].val) //当存在儿子且当前位置值不等于x
u=t[u].ch[x>t[u].val];//跳到儿子,找x的父节点
splay(u,0);
}
inline void insert(int x){
int u=root,fa=0;
while(u&&t[u].val!=x){//存在u且不是当前位置的值
fa=u;//向下u的儿子,父节点变为u
u=t[u].ch[x>t[u].val];//比u大往右找,否则往左找
}
if(u) t[u].cnt++;//存在u,该位置数量+1
else{//不存在就新增节点
u=++tot;
if(fa) t[fa].ch[x>t[fa].val]=u;//父节点非根
t[u].ch[0]=t[u].ch[1]=0;
t[tot].fa=fa;
t[tot].val=x;
t[tot].cnt=1;
t[tot].siz=1;
}
splay(u,0);//保证平衡
}
inline int next(int x,int f){//前驱0,后继1
find(x);//找到x并延伸到根节点
int u=root;//若x存在根节点即为其父
if(t[u].val>x&&f) return u;//当前节点值大于x且要查后继
if(t[u].val<x&&!f) return u;//当前节点值小于x且要查前驱
u=t[u].ch[f];//后继右儿子,前驱左儿子
while(t[u].ch[f^1]) u=t[u].ch[f^1];//反着跳转
splay(u,0);
return u;
}
inline void Delete(int x){
int last=next(x,0);//找前驱
int nxt=next(x,1);//找后继
splay(last,0);//前驱转到根
splay(nxt,last);//后继转到根节点下面
int del=t[nxt].ch[0];//x为后继的左儿子
if(t[del].cnt>1){
t[del].cnt--;
splay(del,0);
}
else t[nxt].ch[0]=0;//删节点
}
inline int kth(int x){
int u=root;
if(t[u].siz<x) return 0;//树上点不够
while(1){
int y=t[u].ch[0];//左儿子
if(x>t[y].siz+t[u].cnt){//左儿子和该节点大小不够
x-=t[y].siz+t[u].cnt;
u=t[u].ch[1];//在右儿子上找
}
else if(t[y].siz>=x) u=y;
else{
splay(u,0);
return t[u].val;
}
}
splay(u,0);
}
int main(){
std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;
insert(1e9);//哨兵
insert(-1e9);
for(int i=1;i<=n;i++){
cin>>opt>>xx;
switch(opt){
case 1:insert(xx);break;
case 2:Delete(xx);break;
case 3:insert(xx);find(xx);cout<<t[t[root].ch[0]].siz<<'\n';Delete(xx);break;
case 4:cout<<kth(xx+1)<<'\n';break;
case 5:insert(xx);cout<<t[next(xx,0)].val<<'\n';Delete(xx);break;
case 6:insert(xx);cout<<t[next(xx,1)].val<<'\n';Delete(xx);break;
}
}
return 0;
}