这份题解的特点:
- 堆的实现是用迭代法写的。
- 用一个专门的数组记录第 k 个插入的数字当前的值。
#pragma GCC push_options
#pragma GCC optimize ("-Ofast")
#include <bits/stdc++.h>
constexpr int N = 100000;
struct MinHeap final {
int arr[N];
int len = 0;
[[nodiscard]] constexpr int top() const noexcept
{
return arr[0];
}
constexpr void push(int newValue) noexcept
{
int i = len++;
while (i) {
int p = (i + 1) / 2 - 1;
if (arr[p] <= newValue) break;
arr[i] = arr[p];
i = p;
}
arr[i] = newValue;
}
constexpr void pop() noexcept
{
int v = arr[--len], i = 0;
while (true) {
int j = 2 * i + 1;
if (j >= len) break;
if (j + 1 != len && arr[j + 1] < arr[j]) ++j;
if (v <= arr[j]) break;
arr[i] = arr[j];
i = j;
}
arr[i] = v;
}
} numbers, to_pop;
constexpr void flushHeapPops() noexcept
{
while (to_pop.len != 0 && to_pop.top() == numbers.top()) {
to_pop.pop();
numbers.pop();
}
}
struct BoundedArray final {
int buffer[N];
int len = 0;
constexpr void push(int x) noexcept
{
buffer[len++] = x;
}
constexpr int& operator[](int offset) noexcept
{
return buffer[offset];
}
} insert_sequence;
int main()
{
char cmd[3];
int n, k, x;
scanf("%d", &n);
for (int i = 0; i != n; ++i) {
scanf("%s", cmd);
if (cmd[0] == 'I') {
scanf("%d", &x);
numbers.push(x);
insert_sequence.push(x);
} else if (cmd[0] == 'P') {
flushHeapPops();
printf("%d\n", numbers.top());
} else if (cmd[0] == 'C') {
// Changing a value is equivalent to deleting the old and inserting the new.
scanf("%d%d", &k, &x);
to_pop.push(insert_sequence[k - 1]);
numbers.push(x);
insert_sequence[k - 1] = x;
} else if (cmd[1] == 'M') {
flushHeapPops();
numbers.pop();
} else {
scanf("%d", &k);
to_pop.push(insert_sequence[k - 1]);
}
}
}