#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
const int N = 1e5+10;
int h[N],hp[N],ph[N];//h[]堆,ph[i]指向该点i所在的堆的下标,hp[i]指向所在的ph[]的位置,即hp[i]=k 则ph[k]=i;
int cnt;//充当指针,同时表明堆每个元素的位置
void swap(int &a,int &b)
{
int t = a;
a = b;
b = t;
}
void heap_swap(int a, int b)
{
swap(ph[hp[a]],ph[hp[b]]);
swap(hp[a], hp[b]);
swap(h[a], h[b]);
}
void down(int u)
{
int t = u;
if (2 * u <= cnt && h[t] > h[2 * u])
{
t = 2 * u;
}
if (2 * u + 1 <= cnt && h[t] > h[2 * u + 1])
{
t = 2 * u + 1;
}
if (t != u)
{
heap_swap(t, u);
down(t);
}
}
void up(int u)
{
while (u / 2 && h[u]<h[u/2])
{
heap_swap(u, u / 2);
u >>= 1;
}
}
int main()
{
int n;
int m = 0;//表明第K个插入数
cin >> n;
while (n--)
{
string op;
int k, x;
cin >> op;
if ("I" == op)
{
cin >> x;
cnt++;
m++;
h[cnt] = x;
ph[m] = cnt;//指向堆的下标
hp[cnt] = m;//指向ph的下标
up(cnt);//插入堆,由于堆是完全二叉树插入相当于插入叶子节点
}
else if ("PM" == op)
{
cout << h[1] << endl;
}
else if ("DM" == op)
{
heap_swap(1, cnt);
cnt--;//调整堆的结点个数
down(1);//调整堆,使其保持小根堆的定义
}
else if ("D" == op)
{
cin >> k;
k = ph[k];//取出第K个插入的数在堆中位置的下标
heap_swap(k, cnt);
cnt--;//删除
up(k);//使之保持小根堆
down(k);
}
else
{
cin >> k >> x;
k = ph[k];
h[k] = x;
up(k);
down(k);
}
}
return 0;
}