正式比赛时我们肯定不愿意手写堆,不过作为一道模板题,我们还是手写一下并体会堆的过程比较好。
小根堆的存在形式是一棵二叉树,根节点是最小的数。我们初始化树上所有节点的权值为INF。当要添加一个数x时,我们把当前编号+1,把数放在那儿,并记录下当前编号。然后不断将其与其父亲结点进行比较,如果小就交换,并让记录下来的该数的编号除以2。(对于二叉树来说 父亲节点编号为x,那么它两个儿子节点编号必然是x*2与x*2+1,代表左儿子与右儿子)。这样如果要找最小元素,只需输出根节点就行了,时间复杂度O(1)。如果要删除最小值,那我们记录根节点编号为1,并不断将其与其子节点比较,如果左比右大就让左代替,并把编号*2,反之右大右代替,编号*2+1。最后把根节点对应的编号变成INF。
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=1000010;
const int INF=0x3f3f3f3f;
int num[maxn*8];
int tot=0;
void add(int x)
{
tot++;
num[tot]=x;
int q=tot;
while(num[q]<num[q/2]&&q!=1)
{
swap(num[q],num[q/2]);
q=q/2;
}
}
int top()
{
return num[1];
}
void pop()
{
int q=1;
while(num[q*2]!=INF||num[q*2+1]!=IN