#include<iostream>
#include<cstdio>
#include<limits.h>
using namespace std;
const int N = 2e4 + 10;
int ans = 0;
struct node
{
int val, ls, rs, cnt, size;
}t[N];
int cnt = 0;
void insert(int x, int val)
{
t[x].size++;
if (t[x].val == val)
{
t[x].cnt++;
return;
}
if (val < t[x].val)
{
if (t[x].ls)
{
insert(t[x].ls, val);
}
else
{
cnt++;
t[x].ls = cnt;
t[cnt].size = t[cnt].cnt = 1;
t[cnt].val = val;
}
}
else
{
if (t[x].rs)
{
insert(t[x].rs, val);
}
else
{
cnt++;
t[x].rs = cnt;
t[cnt].size = t[cnt].cnt = 1;
t[cnt].val = val;
}
}
}
void query1(int x, int val,int rank)
{
if (t[x].val == val)
{
printf("%d\n", t[t[x].ls].size + rank + 1);
return;
}
if (val < t[x].val)
query1(t[x].ls, val,rank);
else
query1(t[x].rs, val, rank + t[t[x].ls].size+t[x].cnt);
}
int query2(int x, int rank)
{
if (x == 0) return INT_MAX;
if (t[t[x].ls].size >= rank)
return query2(t[x].ls, rank);
if (t[t[x].ls].size + t[x].cnt >= rank)
return t[x].val;
return query2(t[x].rs, rank-t[t[x].ls].size-t[x].cnt);
}
int qfr(int x, int val, int ans)
{
if (t[x].val >= val)
{
if (t[x].ls == 0) return ans;
else return qfr(t[x].ls, val, ans);
}
else
{
if (t[x].rs == 0) return t[x].val < val ? t[x].val : ans;
else return qfr(t[x].rs, val, t[x].val);
}
}
int qne(int x, int val, int ans)
{
if (t[x].val <= val)
{
if (t[x].rs == 0) return ans;
else return qne(t[x].rs, val, ans);
}
else
{
if (t[x].ls == 0) return t[x].val > val ? t[x].val : ans;
else return qne(t[x].ls, val, t[x].val);
}
}
int main()
{
int q;
cin >> q;
while (q--)
{
int x, y;
cin >> x >> y;
switch (x)
{
case 5:
{
if (cnt == 0)
{
cnt++;
t[cnt].cnt = t[cnt].size = 1;
t[cnt].val = y;
}
else
insert(1, y);
break;
}
case 4:
{
cout<<qne(1, y, INT_MAX)<<endl;
break;
}
case 3:
{
cout<<qfr(1, y, -INT_MAX)<<endl;
break;
}
case 2:
{
cout << query2(1, y) << endl;
break;
}
default:
{
query1(1, y, 0);
break;
}
}
}
return 0;
}