题目
AcWing 839. 模拟堆
#include <iostream>
#include <string>
#include <utility>
using namespace std;
const int N = 100010;
// h[i]:堆中第 i 个位置存储的值
int h[N];
// hp[k]:第 k 个插入的数目前位于堆中的哪个位置
int hp[N];
// ph[i]:堆中第 i 个位置存储的是第几个插入的数
int ph[N];
// heap_size:当前堆中元素数量
// insert_count:总共执行过多少次插入操作
int heap_size, insert_count;
// 交换堆中的两个位置
void heap_swap(int a, int b) {
swap(h[a], h[b]);
// 更新“插入编号 -> 堆位置”的映射
swap(hp[ph[a]], hp[ph[b]]);
// 更新“堆位置 -> 插入编号”的映射
swap(ph[a], ph[b]);
}
// 向下调整
void down(int u) {
int t = u;
if (u * 2 <= heap_size && h[u * 2] < h[t]) {
t = u * 2;
}
if (u * 2 + 1 <= heap_size && h[u * 2 + 1] < h[t]) {
t = u * 2 + 1;
}
if (t != u) {
heap_swap(t, u);
down(t);
}
}
// 向上调整
void up(int u) {
while (u / 2 > 0 && h[u] < h[u / 2]) {
heap_swap(u, u / 2);
u /= 2;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
while (n--) {
string op;
cin >> op;
if (op == "I") {
int x;
cin >> x;
heap_size++;
insert_count++;
h[heap_size] = x;
// 第 insert_count 个插入的数位于 heap_size
hp[insert_count] = heap_size;
// 堆中 heap_size 位置存的是第 insert_count 个插入的数
ph[heap_size] = insert_count;
up(heap_size);
} else if (op == "PM") {
cout << h[1] << '\n';
} else if (op == "DM") {
// 把堆顶和最后一个元素交换,再删除最后一个元素
heap_swap(1, heap_size);
heap_size--;
down(1);
} else if (op == "D") {
int k;
cin >> k;
// 找到第 k 个插入的数目前在堆中的位置
int position = hp[k];
// 将它和最后一个元素交换,再删除
heap_swap(position, heap_size);
heap_size--;
// 交换过来的元素可能需要向上或向下调整
up(position);
down(position);
} else if (op == "C") {
int k, x;
cin >> k >> x;
// 找到第 k 个插入的数目前在堆中的位置
int position = hp[k];
h[position] = x;
// 修改后可能变小,也可能变大
up(position);
down(position);
}
}
return 0;
}