#include<stdio.h>
#include<stdlib.h>
#define MAXN 200100
const int INF = 1000000100;
int elems[MAXN], loc[MAXN], rloc[MAXN];
typedef struct HEAP HEAPSHADOW;
struct HEAP{
int size;
int counter;
size_t elem_size;
void* elements;
int* location;
int* reverselocation;
char (*compare)( void* , void*);
void (*swap)( HEAPSHADOW*, int, int );
void (*push_up)( HEAPSHADOW*, int);
void (*push_down)( HEAPSHADOW*, int);
void (*insert_element)( HEAPSHADOW*, void*);
void (*delete_nth_inserted)( HEAPSHADOW*, int);
void* (*top)( HEAPSHADOW* );
};
typedef struct HEAP HEAP;
void* top( HEAP* this ){
return &((int*)this->elements)[0];
}
char compare( void* a, void* b ){
int inta = *( (int*) a), intb = *( (int*) b);
return (inta > intb ? 1 : 0);
}
void swap( HEAP* this, int a, int b ){
int c = ((int*)this->elements)[a];
((int*)this->elements)[a] = ((int*)this->elements)[b];
((int*)this->elements)[b] = c;
c = this->location[ this->reverselocation[a] ];
this->location[ this->reverselocation[a] ] = this->location[ this->reverselocation[b] ];
this->location[ this->reverselocation[b] ] = c;
c = this->reverselocation[a];
this->reverselocation[a] = this->reverselocation[b];
this->reverselocation[b] = c;
}
void push_up( HEAP* this, int pos ){
int dad = pos / 2;
while( dad > 0 && this->compare( &((int*)this->elements)[dad - 1], &((int*)this->elements)[pos - 1] ) ){
this->swap(this, dad - 1, pos - 1 );
pos = dad;
dad = pos / 2;
}
}
void push_down( HEAP* this, int pos ){
char flag = 1;
int son1, son2;
while( flag ){
son1 = pos * 2;
son2 = pos * 2 + 1;
if( son1 <= this->size && son2 <= this->size )
if( ((int*)this->elements)[ pos - 1 ] < ((int*)this->elements)[ son1 - 1 ] && ((int*)this->elements)[ pos - 1 ] < ((int*)this->elements)[ son2 - 1 ] )
flag = 0;
else
if( ((int*)this->elements)[ son1 - 1 ] < ((int*)this->elements)[ son2 - 1 ] ){
this->swap( this, pos - 1, son1 - 1 );
pos = son1;
}
else{
this->swap( this, pos - 1, son2 - 1 );
pos = son2;
}
else
if( son1 <= this->size)
if( ((int*)this->elements)[ pos - 1 ] > ((int*)this->elements)[ son1 - 1 ] ){
this->swap( this, pos - 1, son1 - 1 );
pos = son1;
}
else
flag = 0;
else
flag = 0;
}
}
void insert_element( HEAP* this, void* elem_void ){
((int*)this->elements)[this->size] = *( (int*) elem_void );
this->location[ this->counter ] = this->size ;
this->reverselocation[ this->size ] = this->counter;
this->counter++;
this->size++;
this->push_up( this, this->size );
}
void delete_nth_element( HEAP* this, int which ){
which--;
int send_down_index = this->location[ which ] + 1;
this->swap( this, this->location[which], this->size - 1 );
this->size--;
((int*)this->elements)[ this->size ] = -INF;
if( send_down_index < this->size + 1)
this->push_down( this, send_down_index );
}
void init( int N, HEAP** h ){
int* a;
int i;
(*h) = (HEAP* ) malloc( sizeof( HEAP ) );
(*h)->size = 0;
(*h)->counter = 0;
a = (int*) malloc( sizeof( int ) * N );
(*h)->elements = a;
for( i = 0; i < N; i++ )
((int*)(*h)->elements)[i] = -INF;
a = (int*) malloc( sizeof( int ) * N );
(*h)->location = a;
a = (int*) malloc( sizeof( int ) * N);
(*h)->reverselocation = a;
(*h)->top = ⊤
(*h)->compare = &compare;
(*h)->swap = &swap;
(*h)->push_up = &push_up;
(*h)->push_down = &push_down;
(*h)->insert_element = &insert_element;
(*h)->delete_nth_inserted = &delete_nth_element;
}
int main(){
HEAP *my_heap;
int N, val, i, instr;
FILE *in, *out;
in = fopen( "heapuri.in", "r" );
out = fopen( "heapuri.out", "w" );
fscanf(in, "%d", &N);
init( N, &my_heap );
for( i = 0; i < N; i++){
fscanf( in, "%d", &instr );
switch( instr ){
case 1: {
fscanf( in, "%d", &val );
my_heap->insert_element( my_heap, &val );
} break;
case 2: {
fscanf( in, "%d", &val );
my_heap->delete_nth_inserted( my_heap, val );
}break;
case 3: {
fprintf( out, "%d\n", *( (int*) my_heap->top( my_heap ) ) );
}
}
}
return 0;
}