Max - Min Query(multiset语法)
题意
我们有一个整数的multiset,记为\(S\)。\(S\)一开始为空。
给定\(Q\)个操作,并按顺序处理。总共有\(3\)类操作:
- 为\(S\)插入一个元素\(X\)
- 从\(S\)中删除\(m\)个\(x\),其中\(m = \min (c, k)\),其中\(c\)给定,\(k\)为\(S\)中\(x\)的个数。
- 输入\(S\)中的最大值 - 最小值,该操作保证\(S\)非空。
数据范围
\(1 \leq Q \leq 2 \times 10^5\)
思路
本题考查multiset基础语法,这里重点分析第二问。
- erase()操作
如果使用如下代码:
S.erase(3);
那么会将\(S\)中的所有\(3\)全部删除。那么如何只删除一次呢?可以考虑传入迭代器。即:
S.erase(S.find(3));
- count()操作的复杂度
count()的时间复杂度是\(O(k+\log N)\),其中\(N\)是\(S\)中元素的个数,\(k\)是元素\(x\)的个数。
因此,如果第二个操作使用count(),最坏时间复杂度是\(O(Q^2)\)。因此,不能使用S.count()
为了保证时间复杂度,只能使用S.find()
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
multiset<int> s;
int main()
{
int Q;
scanf("%d", &Q);
while(Q --) {
int op;
scanf("%d", &op);
if(op == 1) {
int x;
scanf("%d", &x);
s.insert(x);
}
else if(op == 2) {
int x, c;
scanf("%d%d", &x, &c);
while(c -- && s.find(x) != s.end()) {
s.erase(s.find(x));
}
}
else {
printf("%d\n", *s.rbegin() - (*s.begin()));
}
}
return 0;
}