void down(int u) { int t = u; if (u * 2 <= cnt && h[u * 2] < h[t]) t = u * 2; if (u * 2 + 1 <= cnt && h[u * 2 + 1] < h[t]) t = u * 2 + 1; if (u != t) { swap(h[u], h[t]); down(t); } }
int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i ++ ) scanf("%d", &h[i]); cnt = n;
for (int i = n / 2; i; i -- ) down(i); // 个人不足如果他给我们全部的数据就可以从所以非叶节点开始下沉 保证把最小值放上去
/* 8 I -10 PM I -10 D 1 C 2 8 I 6 PM DM I x,插入一个数 x; PM,输出当前集合中的最小值; DM,删除当前集合中的最小值(数据保证此时的最小值唯一); D k,删除第 k个插入的数; C k x,修改第 k个插入的数,将其变为 x; 感悟:细节,细节细节还他妈的是细节,代码没有反馈到所有的情况,例如以前没考虑到修改的操作,如果你把修改和删除放到一起不能保证当前的值是最小值 如果你在增加一个新的值来解决但不确定那个就需要用一个map来记录总归是难在没有办法实现从次数到位置的映射,这其实很容易实现也不知道脑子抽啥风了,理解的方向是给定两个数组一个 是从时间到空间的映射一个是从空间到时间的映射 */
int h[N], ph[N], hp[N], cnt; // 通过两个数组就可以实现两个数组之间的映射, hp 从地址到 第几次操作的映射 ph 从第几次操作到地址的映射
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 (u * 2 <= cnt && h[u * 2] < h[t]) t = u * 2; if (u * 2 + 1 <= cnt && h[u * 2 + 1] < h[t]) t = u * 2 + 1; if (u != t) { heap_swap(u, t); 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, m = 0; scanf("%d", &n); while (n -- ) { char op[5]; int k, x; scanf("%s", op); if (!strcmp(op, "I")) { scanf("%d", &x); cnt ++ ; m ++ ; ph[m] = cnt, hp[cnt] = m; h[cnt] = x; 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]; heap_swap(k, cnt); cnt -- ; up(k); down(k); } else { scanf("%d%d", &k, &x); k = ph[k]; h[k] = x; up(k); down(k); } }