##堆的初始化,以及排序
//无映射关系的堆
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[N];
int cnt ;
void down(int x)
{
int t = x;
if ((2*x) <= cnt && a[2*x] < a[t]) t = 2 * x;
if ((2 * x + 1) <= cnt && a[2 * x + 1] < a[t]) t = 2 * x + 1;//比较与左右儿子的大小
if (t != x)
{
swap (a[x],a[t]);
down(t);
}
}
int main()
{
int n,m;
cin>>n>>m;
for (int i = 1 ; i <= n ; i ++) cin>>a[i];
cnt = n;
for (int i = n/2 ; i ; i --) down(i);//初始化堆
while (m --)
{
cout<<a[1]<<" ";
a[1] = a[cnt];
cnt --;
down(1);
}//输出最小的元素,并每次都删除,因为用一维数组来储存,删除第一个元素不方便,所以把a[1] = a[cnt] ,再进行down()操作
return 0;
}
//有映射关系的堆
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[N] , ph[N] ,hp[N];
int m ,cnt;
void head_swap(int x , int y) // x ,y 是堆数组的下标
{
//交换值以及映射关系
swap(ph[hp[x]],ph[hp[y]]);
swap(hp[y],hp[x]);
swap(a[x], a[y]);//ph[k] = i 表示 第k 个插入的元素在数组中对应的下标是i
//hp[i] = k 表示下表是i 的元素是k个插入的
}
void down(int x)
{
int t = x;
if (2*x < cnt && a[2*x] < a[t]) t = 2 * x;
if (2 * x + 1 < cnt && a[2 * x + 1] < a[t]) t = 2 * x + 1;
if (t != x)
{
head_swap(t,x);
down(t);
}
}
void up (int x)
{
while (x / 2 && a[x] < a[x / 2])
{
head_swap(x , x/2);
x /= 2;
}
}
int main()
{
int n;
cin>>n;
while (n --)
{
int k,x;
string op;
cin>>op;
if (op == "PM") cout<<a[1];
else if (op == "I")
{
cin>>x;
cnt ++;
m ++;
ph[m] = cnt , hp[cnt] = m;
a[cnt] = x;
up(cnt);
}
else if (op == "DM")
{
head_swap(1,cnt);
cnt --;
down(1);
}
else if (op == "D")
{
cin>>k;
k = ph[k];
head_swap(k,cnt);
cnt --;
up(k);
down(k);
}
else
{
cin>>k>>x;
k = ph[k];
a[k] = x;
down(k);
up(x);
}
}
return 0;
}