// 插入一个数 heap[++ size] = x; up(size);
// 求集合当中的最小值 heap[1]
// 删除最小值 heap[1] = heap[size]; size --; down(1);
// 删除任意一个元素 heap[k] = heap[size]; size --; up(k); down(k);
// 修改任意一个元素 heap[k] = x; up(k); down(k);
#include <iostream>
#include <string.h>
using namespace std;
const int N = 100010;
int h[N], hp[N], ph[N];
int cnt, idx; // cnt堆中元素个数, idx现在利用到哪个空间了
void heap_swap(int a, int b)
{
swap(h[a], h[b]); // 交换值是最基本的,a和b是堆的下标。
swap(hp[a], hp[b]); // 交换hp[a], hp[b]这里hp[a]和hp[b]存放的是hp[i]是他是第几个存进来的
swap(ph[hp[a]], ph[hp[b]]); //ph[t]数组是说建堆时第t个元素目前在h数组的哪个位置
}
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 (u != t)
{
heap_swap(t, u);
down(t);
}
}
void up(int u)
{
while (u / 2 && h[u / 2] > h[u])
{
heap_swap(u / 2, u);
u /= 2;
}
}
int main()
{
int n;
scanf("%d", &n);
while (n --)
{
char op[10];
int k, x;
scanf("%s", op);
if (!strcmp(op, "I"))
{
scanf("%d", &x);
cnt ++;
idx ++;
h[cnt] = x;
hp[cnt] = idx, ph[idx] = cnt;
up(cnt); //注意这里并不交换1和cnt,只需要up(cnt)就行
}
else if (!strcmp(op, "PM"))
printf("%d\n", h[1]);
else if (!strcmp(op, "DM"))
{
heap_swap(1, cnt);
cnt --;
down(1);
}
else if (!strcmp(op, "D"))
{
scanf("%d", &k);
k = ph[k]; // 找到第k个元素的堆下标
heap_swap(k, cnt);
cnt --;
down(k);
up(k);
}
else
{
scanf("%d%d", &k, &x);
k = ph[k];
h[k] = x;
down(k), up(k);
}
}
return 0;
}