1. 程式人生 > 實用技巧 >「題解」洛谷 P1801 黑匣子

「題解」洛谷 P1801 黑匣子

題目

P1801 黑匣子

簡化題意

給你一堆數,每次讓你求前多少個數中的第 \(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;
}