题意
有 $N$ 个人,他们的编号分别为 $1 ... N$。现在有三种操作:
- 柜台呼叫尚未被呼叫的编号最小的人。
- 表示编号为 $x$ 的人来到了柜台(保证 $x$ 已经被呼叫过一次及以上)
询问已经被呼叫但是没有来到柜台的人中的最小编号。
题解
我们发现一个人有三种状态:没有被呼叫,呼叫了但没来,被呼叫且来了。因此我们用两个小根堆维护前两个状态的人(最后一个状态的人相当于不会在被操作或询问了,所以不用维护)。因此对于操作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; }