AcWing 839. 模拟堆
原题链接
简单
作者:
acm_wf
,
2021-03-16 17:02:05
,
所有人可见
,
阅读 224
这题刚开始理解挺绕的,仔细分析一下
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int n;
//ph 指 第几个插入的数字到堆中下标的映射
//hp 指 堆中下标的映射到第几个插入的数字
int hp[N], ph[N], h[N];
//一个记录堆的个数
//一个记录是第几个插入的数据
int cnt, m;
void heap_swap(int t, int u){
//交换两个数字,所有的一切都要交换
//值肯定要交换
//堆位置下标对应的插入次数也要交换
//相应地,插入次数对应的堆位置下标也要交换
//给的参数是堆中的位置下标!!!
//首先指针得变化,堆中下标对应的插入次数是hp[t]
//堆中下标对应的插入次数是hp[t],而这个插入次数在堆中对应的下标就是ph[hp[t]]
//现在要交换,自然就这样交换
swap(ph[hp[t]], ph[hp[u]]);
//堆中数字对应的插入次数也变了
//强力建议画图演示!!!!
swap(hp[t], hp[u]);
swap(h[t], h[u]);
}
//这个是堆中的下标
void down(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(t != u){
heap_swap(t, u);
down(t);
}
}
void up(int u){
while( u / 2 && h[u / 2] > h[u]){
heap_swap(u, u / 2);
u /= 2;
}
}
int main(){
cin >> n;
while(n --){
string op;
int k, x;
cin >> op;
if(op == "I"){
cin >> x;
cnt ++;
m ++;
h[cnt] = x;
//互相映射
hp[cnt] = m;
ph[m] = cnt;
up(cnt);
}else if(op == "PM") cout << h[1] <<endl;
else if(op == "DM"){
heap_swap(1, cnt);
//个数减一
cnt--;
down(1);
}else if(op == "D"){
//输入的是插入的数字自然找ph
cin >> k;
k = ph[k];
heap_swap(k, cnt);
cnt --;
down(k);
up(k);
}else{
cin >> k >> x;
k = ph[k];
h[k] = x;
down(k);
up(k);
}
}
return 0;
}