P3378 【模板】堆
时间限制 1.00s
内存限制 512.00MB
题目描述
给定一个数列,初始为空,请支持下面三种操作:
1.给定一个整数\(x\),请将\(x\)加入到数列中。
2.输出数列中最小的数。
3.删除数列中最小的数(如果有多个数最小,只删除\(1\)个)。
输入格式
第一行是一个整数,表示操作的次数\(n\)。
接下来\(n\)行,每行表示一次操作。每行首先有一个整数\(op\)表示操作类型。
- 若\(op=1\),则后面有一个整数\(x\),表示要将\(x\)加入数列。
- 若\(op=2\),则表示要求输出数列中的最小数。
- 若\(op=3\),则表示删除数列中的最小数。如果有多个数最小,只删除\(1\)个。
输出格式
对于每个操作\(2\),输出一行一个整数表示答案。
输入输出样例
输入 #1
5
1 2
1 5
2
3
2
输出 #1
2
5
说明/提示
数据规模与约定
-
对于\(30\%\)的数据,保证\(n \leq 15\)。
-
对于\(70\%\)的数据,保证\(n \leq 10^4\)。
-
对于\(100\%\)的数据,保证\(1\leq n \leq 10^6, \; 1\leq x < 2^{31}, \; op \in \{1,2,3\}\)。
手写版
推荐观看来自henry_y的浅析基础数据结构-二叉堆
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e6+5;
int que[N],cnt;
void Insert(int x){
que[++cnt]=x;
int tmp=cnt;
while(tmp!=1){
int fa=tmp>>1;
if(que[fa]<=que[tmp]) break;
swap(que[fa],que[tmp]);
tmp=fa;
}
}
void Delete(){
swap(que[1],que[cnt]); --cnt;
int tmp=1;
while((tmp<<1)<=cnt){
int ls=tmp<<1,mins=ls,rs=tmp<<1|1;
if(rs<=cnt&&que[rs]<=que[ls]) mins=rs;
if(que[tmp]<=que[mins]) break;
swap(que[tmp],que[mins]);
tmp=mins;
}
}
int main(){
int n;
scanf("%d",&n);
while(n--){
int op,x;
scanf("%d",&op);
if(op==1){ scanf("%d",&x); Insert(x); }
else if(op==2) printf("%d\n",que[1]);
else Delete();
}
return 0;
}
priority_queue版
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1e6+5;
struct node{ int a; };
bool operator < (node x,node y){
return x.a>y.a;
}
priority_queue<node>q;
int main(){
int n;
scanf("%d",&n);
while(n--){
int op,x;
scanf("%d",&op);
if(op==1){ scanf("%d",&x); q.push(node{x}); }
else if(op==2) printf("%d\n",q.top().a);
else q.pop();
}
return 0;
}