1. 程式人生 > 其它 >Max - Min Query(multiset語法)

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;
}