P3378 【模板】堆


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;
}
原文地址:https://www.cnblogs.com/Potrem/p/Luogu_P3378.html