看注释即可,主要为了记录需要记录的关键点
不太算题解,仅仅把不好理解的地方做了一点人性化的注释!
参考代码:
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int n, m, h[N], hp[N], ph[N], siz;
// m 为插入的次序 siz为堆中元素个数
// h:heap p:pointer
// hp[k]:堆中下标为k的是第几次插入的
// ph[k]:第k次插入对应的堆中的下标
//
// a, b 为下标
// swap 三次交换可以任意互换
void heap_swap(int a, int b){
swap(h[a], h[b]);
swap(hp[a], hp[b]);
// a b为下标,ph的下标存的是第几次插入,需要用hp数组来索引第几次插入
swap(ph[hp[a]], ph[hp[b]]);
}
// x 为下标
void down(int x){
int t = x;
if(x * 2 <= siz && h[x * 2] < h[t]) t =x * 2;
if(x * 2 + 1 <= siz && h[x * 2 + 1] < h[t]) t = x * 2 + 1;
if(x != t){
// 与普通堆不同,此处需要传下标
heap_swap(x, t);
down(t);
}
}
// x 为下标
void up(int x){
while(x / 2 && h[x / 2] > h[x]){
// 与普通堆不同,此处需要传下标
heap_swap(x, x / 2);
x /= 2;
}
}
int main(){
cin >> n;
while(n--){
string s; int k, x;
cin >> s;
if(s == "I"){
cin >> x;
m ++, siz ++;
ph[m] = siz, hp[siz] = m;
h[siz] = x, up(siz);
}else if(s == "PM"){
cout << h[1] << endl;
}else if(s == "DM"){
heap_swap(1 ,siz);
siz --; down(1);
}else if(s == "D"){
cin >> k;
int t = ph[k];
heap_swap(t, siz);
siz --;
up(t), down(t);
}else if(s == "C"){
cin >> k >> x;
int t = ph[k];
h[t] = x;
down(t), up(t);
}
}
return 0;
}