小根堆性质: 左儿子=>根节点<=右儿子
三个操作:1.添加x O(logn) 2.查询根顶O(1) 3.删除根节点 O(logn)
添加:末尾先加x,然后不断与更小的上移(交换)
删除:先将点1跟k交换,然后点1不断下移(交换),跟更小的儿子交换
保持性质不变
//luoguP3378 小根堆模板
#include<stdio.h>
#include<math.h>
#include<iostream>
#include<string.h>
using namespace std;
#define ll long long
namespace Heap{
int h[1000005];int k=0;
void add(int x){
h[++k]=x;
int y=k;
while(y>1&&h[y/2]>h[y]){
swap(h[y/2],h[y]);
y=y/2;
}
}
int get(){
return h[1];
}
void pop(){
swap(h[1],h[k]);--k;
int x=1,y=2;
while((y<=k&&h[y]<h[x])||(y+1<=k&&h[y+1]<h[x])){
if(y+1<=k&&h[y]>h[y+1])y++;//选y还是y+1
swap(h[x],h[y]);
x=y;y*=2;
}
}
}
int main(){
int n;cin>>n;
while(n--){
int t;cin>>t;
if(t==1){
int x;cin>>x;
Heap::add(x);
}
if(t==2){
cout<<Heap::get()<<endl;
}
if(t==3){
Heap::pop();
}
}
system("pause");
return 0;
}