ABC294D 题解

题解 · 2023-03-21

题意

有 $N$ 个人,他们的编号分别为 $1 ... N$。现在有三种操作:

  1. 柜台呼叫尚未被呼叫的编号最小的人。
  2. 表示编号为 $x$ 的人来到了柜台(保证 $x$ 已经被呼叫过一次及以上)
  3. 询问已经被呼叫但是没有来到柜台的人中的最小编号。

    题解

    我们发现一个人有三种状态:没有被呼叫,呼叫了但没来,被呼叫且来了。因此我们用两个小根堆维护前两个状态的人(最后一个状态的人相当于不会在被操作或询问了,所以不用维护)。因此对于操作1,我们询问状态1的人中编号最小的人,将其变成状态2,对于操作2,我们直接将指定的 $x$ 从状态2堆中删除。

    #include <iostream>
    #include <queue>
    using namespace std;
    int n, m;
    priority_queue <int, vector<int>, greater<int>> q1, q2, d;
    int main () {
      ios::sync_with_stdio (false), cin.tie (0);
      cin >> n >> m;
      for (int i = 1; i <= n; i++) q1.push(i);
      while (m--) {
     int op, x;
     cin >> op;
     if (op == 1) {
       q2.push(q1.top());
       q1.pop();
     } else if (op == 2) {
       cin >> x;
       d.push(x);
     } else {
       while (!d.empty() && !q2.empty() && d.top() == q2.top())
         d.pop(), q2.pop();
       cout << q2.top() << endl;
     }
      }
      return 0;
    }
题解
Theme Jasmine by Kent Liao