#include<iostream>
using namespace std;
int cnt = 1;//用来记录目前编号
//本题构造数据结构所需特性
// 1.有序性
// 2.记录当前搜索的点的值
//其中含有left(左子树),right(右子树),value,num(一个value含有个数),
//size(遍历到的当前节点,当前节点及当前节点左子树右子树的大小)
// 3.记录当前搜索的点前面有多少个数,后面有多少个数//知道排名
// 4.可以二分查找
struct node {
int left, right;
int value;
int num;
int size;
}t[10005];
//各个步骤逻辑
// 1.查询x的排名是多少query1(x,root)//确定参数
// 从根结点出发//确定遍历顺序,先序(比较大小)
// (1)x<t[root].value query1(x,t[root].left)
// (2) x==t[root].value return t[t[root].left].size//确定返回条件
// //返回条件,借助size返回编号排序
// (3)x>t[root].value query1(x,t[root].right)
// size=t[t[root].left].size+t[root].num//右子树编号大小
int query1(int x, int root) {
if (root == 0) return 1;
if (x < t[root].value) return query1(x, t[root].left);
if (x == t[root].value) return t[t[root].left].size + 1;
if (x > t[root].value) return (query1(x, t[root].right) + t[t[root].left].size + t[root].num);
}
// 2.查询排名为x的值是多少query2(x,root)
// 从根结点出发//确定遍历顺序,先序(比较大小)
// (1)x<=t[t[root].left].size query1(x,t[root].left)
// (2) x<=t[t[root].left].size +t[root].num return t[root].value//确定返回条件
// (3)qurey2(x-t[t[root].left].size -t[root].num,t[root].right)//在右子树中寻找
int query2(int x, int root) {
if (x <= t[t[root].left].size) return query2(x, t[root].left);
if (x <= t[t[root].left].size + t[root].num) return t[root].value;
else return query2(x - t[t[root].left].size - t[root].num, t[root].right);
}
//3.求x的前驱
// (1)计算x的排名tmp tmp=query1(x,root)
// 对tmp特判,若没有前驱(tmp==1)return−2147483647
// 否则(2)排名为tmp-1的值 query2(tmp-1,root)
//4.求x的后继
// (1)计算x+1的排名tmp tmp=query1(x,root)
// 对tmp特判,若没有后继(tmp==当前节点个数+1)return−2147483647
// 否则(2)排名为tmp的值 query2(tmp,root)
//5.插入x insert(x,root)
// (1)判断当前插入的位置是否为空 root==0(叶子节点) cnt==1(空树) 新建一个节点
// (2)x<t[root].value insert(x,t.[root].left);
// if(t.[root].left==0) 新建一个节点
// else insert(x,t.[root].left);
// (3)x=t[root].value t[root].num++;
// (4)x>t[root].value
// if(t.[root].right5==0) 新建一个节点
// else insert(x,t.[root].right);
void insert(int x, int root) {
if (cnt == 1) {
node tmp = { 0,0,x,1,1 };
t[cnt] = tmp;
cnt++;
}
else {
if (x < t[root].value) {
if (t[root].left == 0) {
node tmp = { 0,0,x,1,1 };
t[cnt] = tmp;
t[root].left = cnt;
cnt++;
}
else insert(x, t[root].left);
}
if (x == t[root].value) t[root].num++;
if (x > t[root].value) {
if (t[root].right == 0) {
node tmp = { 0,0,x,1,1 };
t[cnt] = tmp;
t[root].right = cnt;
cnt++;
}
else insert(x, t[root].right);
}
}
t[root].size = t[t[root].left].size + t[t[root].right].size + t[root].num;
}
int main() {
int n, op, x;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> op >> x;
if (op == 1)cout << query1(x, 1)<<endl;
if (op == 2)cout << query2(x, 1)<<endl;
if (op == 3) {
int tmp = query1(x, 1);
if (tmp == 1) cout << -2147483647 << endl;
else cout << query2(tmp - 1, 1);
}
if (op == 4) {
int tmp = query1(x + 1, 1);
if(tmp==cnt) cout<< -2147483647 << endl;
else cout << query2(tmp , 1);
}
if (op == 5) {
insert(x, 1);
}
}
return 0;
}