#include <iostream>
#include <vector>
#include <utility>
#define MAX 200009
using namespace std;
int N, K;
vector<pair<int, int>> H(MAX); // the node and the position in posHeap
vector<int> inserted_nodes(MAX, 0);
vector<int> posHeap(MAX, 0);
int father(int node){
return node/2;
}
int left_son(int node){
return 2*node;
}
int right_son(int node){
return node*2+1;
}
void sift(int node){
int son;
do {
son = 0;
// Alege un fiu mai mare ca tatal.
if (left_son(node) < N) {
son = left_son(node);
if (right_son(node) < N && H[right_son(node)] < H[left_son(node)]) {
son = right_son(node);
}
if (H[son] >= H[node]) {
son = 0;
}
}
if (son) {
posHeap[H[node].second] = son;
posHeap[H[son].second] = node;
swap(H[node], H[son]);
node = son;
}
} while (son);
}
void percolate(int node){
int f, key = H[node].first, pos = H[node].second;
while(node > 1 && key < H[f = father(node)].first){
H[node] = H[f];
posHeap[H[f].second] = node;
node = f;
}
H[node] = make_pair(key, pos);
posHeap[pos] = node;
}
void insertH(int elem){
H[N] = make_pair(elem, K);
posHeap[K] = N;
percolate(N);
N++;
}
void deleteH(int node){
H[node] = H[N-1];
posHeap[H[N-1].second] = node;
N--;
if(node > 1 && H[node] < H[father(node)]){
percolate(node);
}else{
sift(node);
}
}
int main(){
int M, op_code, elem, ith;
freopen("heapuri.in", "r", stdin);
freopen("heapuri.out", "w", stdout);
scanf("%d", &M);
K = 1, N = 1;
for(int i = 0; i < M; i++){
scanf("%d", &op_code);
switch(op_code){
case 1:
scanf("%d", &elem);
inserted_nodes[K] = elem;
insertH(elem);
K++;
break;
case 2:
scanf("%d", &ith);
deleteH(posHeap[ith]);
break;
case 3:
printf("%d\n", H[1].first);
}
}
return 0;
}