#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;
 }










