「題解」洛谷 P1801 黑匣子
阿新 • • 發佈:2020-08-26
題目
簡化題意
給你一堆數,每次讓你求前多少個數中的第 \(k\) 小的數。
思路
大根堆 +小根堆。
沒有詢問前把數都加到大根堆裡,有詢問的時候當大根堆裡的元素不少於 \(k\) 的時候就把堆頂的元素放到小跟堆裡,最後小根堆堆頂的元素就是答案,最後要把小根堆堆頂的元素放回大根堆中。
Code
#include <cstdio> #include <cstring> #include <string> #include <iostream> #include <algorithm> #include <queue> #define MAXN 200001 int n, m, a[MAXN], b[MAXN]; std::priority_queue<int> q1; std::priority_queue<int, std::vector<int>, std::greater<int> > q2; int main() { scanf("%d %d", &n, &m); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); for (int i = 1; i <= m; ++i) scanf("%d", &b[i]); int now = 1, cnt = 0; for (int i = 1; i <= b[now]; ++i) { q1.push(a[i]); while (i == b[now]) { ++cnt; while(q1.size() >= cnt) { int x = q1.top(); q1.pop(); q2.push(x); } int ans = q2.top(); q1.push(ans), q2.pop(); printf("%d\n", ans); ++now; } } return 0; }