【题目来源】
https://www.acwing.com/problem/content/841/
【题目描述】
维护一个集合,初始时集合为空,支持如下几种操作:
- I x,插入一个数 x;
- PM,输出当前集合中的最小值;
- DM,删除当前集合中的最小值(数据保证此时的最小值唯一);
- D k,删除第 k 个插入的数;
- C k x,修改第 k 个插入的数,将其变为 x;
现在要进行 N 次操作,对于所有第 2 个操作,输出当前集合的最小值。
【输入格式】
第一行包含整数 N。
接下来 N 行,每行包含一个操作指令,操作指令为 I x,PM,DM,D k 或 C k x 中的一种。
【输出格式】
对于每个输出指令 PM,输出一个结果,表示当前集合中的最小值。
每个结果占一行。
【数据范围】
1≤N≤10^5
−10^9≤x≤10^9
数据保证合法。
【输入样例】
8
I -10
PM
I -10
D 1
C 2 8
I 6
PM
DM
【输出样例】
-10
6
【算法分析】
● 堆是一棵完全二叉树。
● unordered_map:https://blog.csdn.net/hnjzsyjyj/article/details/131628676
● multiset:https://cplusplus.com/reference/set/multiset/
● 本题的数组模拟实现参见:https://blog.csdn.net/hnjzsyjyj/article/details/146358448
【算法代码】
cpp
#include<bits/stdc++.h>
using namespace std;
multiset<int> h; //heap
unordered_map<int,int> a;
int n,k,x,tot;
string op;
int main() {
cin>>n;
while(n--) {
cin>>op;
if(op=="I") cin>>x, h.insert(x), a[++tot]=x;
else if(op=="PM") cout<<*h.begin()<<endl;
else if(op=="DM") h.erase(h.begin());
else if(op=="D") cin>>k, h.erase(h.find(a[k]));
else cin>>k>>x, h.erase(h.find(a[k])), h.insert(a[k]=x);
}
}
/*
in:
8
I -10
PM
I -10
D 1
C 2 8
I 6
PM
DM
out:
-10
6
*/
【参考文献】
https://www.acwing.com/solution/content/156923/
https://www.cnblogs.com/ddja/p/15898586.html
https://www.acwing.com/solution/content/6100/
https://www.acwing.com/solution/content/5541/
https://www.cnblogs.com/Hayasaka/p/14294147.html