#include <fstream>
#define NMAX 200005
using namespace std;
ifstream fin("heapuri.in");
ofstream fout("heapuri.out");
int t, op, x;
int n, h[NMAX], p[NMAX], pi[NMAX];
int q;
void creare(int [], int&);
void creare_comb(int[], int&);
void afisare(int [], int);
void inserare(int [], int&, int);
void combinare(int [], int, int);
int extrage_min(int [], int&);
void sterge(int [], int&, int);
int main()
{
fin >>t;
for (q = 1; q <= t; ++q)
{
fin >>op;
switch(op)
{
case 1:
fin >>x;
inserare(h, n, x);
break;
case 2:
fin >>x;
sterge(h, n, p[x]);
break;
case 3:
fout <<h[1]<<'\n';
break;
}
}
fout.close();
return 0;
}
void creare(int h[], int &n)
{
int i, x, nr, op;
fin >>n; n = 0;
for (i = 1; i <= nr; ++i)
{
fin >>x;
inserare(h, n, x);
}
}
void creare_comb(int h[], int &n)
{
int i;
fin >>n;
for (i = 1; i <= n; ++i) fin >>h[i];
for (i = n/2; i > 0; --i) combinare(h, n, i);
}
void afisare(int h[], int n)
{
int i;
for (i = 1;i <= n; ++i) fout <<h[i]<<' ';
fout <<'\n';
}
void combinare(int h[], int n, int i)
{
//combin heapurile corecte cu radacinile 2i si 2i+1 cu nodul i
int x = h[i], tata = i, fiu = 2*i;
while (fiu <= n)
{
//daca exista fiu drept si e mai mic
if (fiu+1 <= n && h[fiu+1] < h[fiu]) fiu++;
if (h[fiu] < x)
{
h[tata] = h[fiu];
tata = fiu;
fiu = fiu*2;
}
else break;
}
h[tata] = x;
}
void inserare(int h[], int &n, int x)
{
int poz = n+1, tpoz = poz/2;
while (tpoz > 0 && h[tpoz] > x)
{
h[poz] = h[tpoz];
p[pi[tpoz]] = poz; pi[poz] = pi[tpoz];
poz = tpoz;
tpoz = poz/2;
}
h[poz] = x; n++;
p[n] = poz; pi[poz] = n;
}
int extrage_min(int h[], int &n)
{
int minim = h[1];
h[1] = h[n];
combinare(h, n, 1);
return minim;
}
void sterge(int h[], int &n, int p)
{
h[p] = h[n]; n--;
combinare(h, n, p);
}