int h[N], ph[N], hp[N], cnt; //ph存储第k个插入的数在堆里的下标,hp存储堆中的某个点是第几个插入的元素。维护这样一个数据结构,能够快速找到符合题目要求的第k个插入元素的相关操作。
voidheap_swap(int a, int b)//对维护的数组ph和hp也要进行交换 { swap(ph[hp[a]],ph[hp[b]]);//交换ph中的两个点 swap(hp[a], hp[b]);//交换hp中的两个点 swap(h[a], h[b]);//交换了两个点 }
voiddown(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)//如果上述判断存在,则u和t铁定不一样,那么进行替换,否则跳过 { heap_swap(u, t); down(t); } }
voidup(int u) { while (u / 2 && h[u] < h[u / 2]) #和根节点进行比较即可,因为根节点一定最小,和最小的根节点比较,不会修改另一半的分支 { heap_swap(u, u / 2); u >>= 1; } }
intmain() { 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); } elseif (!strcmp(op, "PM")) printf("%d\n", h[1]); elseif (!strcmp(op, "DM")) { heap_swap(1, cnt); cnt -- ; down(1); } elseif (!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); } }