前言:

  • 堆是一种用于查找最大值/最小值的二叉树
  • 支持添加/减少数据,添加/删除的复杂度是O(logn),查找的复杂度是O(1)

堆的结构:

  • 大根堆:顾名思义,根结点的值比两个子结点都大.
  • 小根堆:顾名思义,根节点的值比两个子结点都小.
  • 堆中结点序号:若根节点序号为1,则根节点的左结点为2(1*2),右结点为3(1*2+1)。堆的全部结点均满足该性质.

堆的实现方式(具体见代码):

  • 添加(add):增加一个结点,并将结点向上推,直到满足堆性质为止
  • 删除根节点(del):将根结点的值设为堆中最后一个结点的值,并删除最后一个结点(删除最后一个结点不会影响堆的结构),再将根节点一直向下推,直到满足堆性质为止
  • 删除任一结点(remove):原理同删除根结点,具体见代码

例题:https://www.luogu.org/problemnew/show/P3378


#include<cstdio>
#include<iostream>
using namespace std;
int heap[50001],n;
void up(int p){
	while(p>1){
		if(heap[p]<heap[p/2]){
			swap(heap[p],heap[p/2]);
			p=p/2;
		}else break;
	}
}
void add(int val){
	heap[++n]=val;
	up(n);
}
int getTop(){
	return heap[1];
}
void down(int p){
	int temp=p*2;
	while(temp<=n){
		if(heap[temp]>heap[temp+1])temp++;
		if(heap[p]>heap[temp]){
			swap(heap[p],heap[temp]);
			p=temp,temp=p*2;
		}else break;
	}
}
void del(){
	heap[1]=heap[n--];
	down(1);
}
void remove(int p){
	heap[p]=heap[n--];
	up(p),down(p);
}
int main(){
	int nn;
	cin>>nn;
	for(int i=1;i<=nn;i++){
		int temp;
		scanf("%d",&temp);
		if(temp==1){
			int addValue;
			scanf("%d",&addValue);
			add(addValue);
		}else if(temp==2){
			printf("%d\n",getTop());
		}else if(temp==3){
			del();
		}
	}
	return 0;
}