对个人认为比较绕的一个部分解释
就是这一行代码swap ( ph[ hp[a] ] , ph[ hp[b] ] );
注释写的非常详细啦!!
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int N=1e5+10;
int h[N],hp[N],ph[N];
//ph[k]代表第k个插入的数在堆中所对应的点
//hp[k]代表堆中点k对应的数是第几个插入的
//hp[k]与ph[k]构成双向映射
int n,m,sz;//sz堆中点的个数
void h_swap(int a,int b)//a,b两个点对应的数进行交换后,他们所对应的ph与hp也要发生改变
{
swap(h[a],h[b]);
swap(ph[hp[a]],ph[hp[b]]);
//该行代码的详注如图所画
swap(hp[a],hp[b]);
}
void down(int x)//小根
{
int t=x;
if(2*x<=sz&&h[2*x]<h[t]) t=2*x;
if(2*x+1<=sz&&h[2*x+1]<h[t]) t=2*x+1;
if(x!=t)
{
h_swap(x,t);//这里也要有变化
down(t);
}
}
void up(int x)//大根
{
while(x/2&&h[x/2]>h[x])
{
h_swap(x/2,x);//同上
x/=2;
}
}
int main()
{
IOS
cin>>n;
while(n--)
{
string s;cin>>s;
if(s=="I")//插入
{
int x;cin>>x;
m++,sz++;
h[sz]=x;
ph[m]=sz,hp[sz]=m;
up(sz);
}else if(s=="PM")
{
cout<<h[1]<<endl;
}else if(s=="DM")//删除堆顶
{
h_swap(1,sz);
sz--;down(1);//前后位置不能调换,保证down的时候里面没有删除前的最小值
}else if(s=="D")//删除第k个插入的数
{
int k;cin>>k;
k=ph[k];//找到第k个插入的数当前在堆中对应的点数
h_swap(k,sz);//与最后一个交换实现删除
sz--;
down(k),up(k);
}else{//修改第k个插入的数
int k,b;cin>>k>>b;
k=ph[k];
h[k]=b;
down(k),up(k);
}
}
return 0;
}