AcWing 839. 模拟堆
原题链接
简单
作者:
Shimmers微光
,
2021-07-17 11:23:57
,
所有人可见
,
阅读 188
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int h[N],cnt; //h[N]用来存储堆元素, cnt表示元素数量
//h是heap(堆)的缩写, p是pointer(下标)的缩写
int hp[N], ph[N]; //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; //t记录root、left、right三个节点的最小值的下标
if(u*2 <= cnt && h[u*2] < h[t]) t = u*2; //root与left比较
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/2] > h[u]) { //不断与root比较
heap_swap(u/2, u);
u /= 2;
}
}
int main() {
int n, m = 0; //m表示操作数
cin >> n;
while(n--) {
string op; int k, x;
cin >> op;
if(op == "I") {
scanf("%d", &x);
cnt++; //堆元素数目加1
m++; //操作数加1
ph[m] = cnt, hp[cnt] = m; //建立映射
h[cnt] = x;
up(cnt); //堆尾上浮
} else if(op == "PM") {
cout << h[1] << endl;
} else if(op == "DM") {
heap_swap(1, cnt); //交换堆顶和堆尾
cnt--; //堆元素数目减1
down(1);//堆顶下沉
} else if(op == "C") {
scanf("%d%d", &k, &x);
k = ph[k]; //找到堆中元素下标
h[k] = x; //修改元素值
down(k), up(k); //下沉或上浮
} else {
scanf("%d", &k);
k = ph[k]; //找到堆中元素下标
heap_swap(k, cnt); //与堆尾元素交换
cnt--; //堆元素数目减1
up(k),down(k); //上浮或下沉
}
}
return 0;
}