NC214362 第k小

题目链接

题目

题目描述

有一个长度为n的数组,值为 a[i], 牛牛想找到数组中第 k 小的数。比如 1 2 2 3 4 6 中,第 3 小的数就是2.

牛牛觉得这个游戏太简单了,想加一点难度,现在牛牛有 m 个操作,每个操作有两种类型。

1 x 1 代表操作一,给数组中加一个元素 x 。(0 ≤ x ≤ 1e9)

2 2 代表操作二,查询第 k 小的数。如果没有 k 个数就输出−1

输入描述

第一行有三个整数,n m k,(1≤n,m,k≤2e5)
第二行包含 n 个整数 a[i] ( 0 ≤ a[i] ≤ 1e9)
接下来m行,每行代表一个操作。具体见题目描述

输出描述

每次查询输出一个第 k 小的数。

示例1

输入

5 4 3
1 2 3 4 5
2
1 1
1 3
2

输出

3
2

题解

知识点:优先队列。

这和输出一个固定序列的第 \(k\) 小不同,这里要维护一个动态变化的序列,故用小顶堆维护前 \(k\) 个数,那么队头就是第 \(k\) 个数。

要注意有可能不足 \(k\) 个数。

时间复杂度 \(O(n\log n + m\log m)\)

空间复杂度 \(O(n + m)\)

代码

#include <bits/stdc++.h>

using namespace std;

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n, m, k;
    cin >> n >> m >> k;
    priority_queue<int> pq;
    for (int i = 0, tmp;i < n;i++) {
        cin >> tmp;
        pq.push(tmp);
        if (pq.size() > k) pq.pop();
    }
    while (m--) {
        int op;
        cin >> op;
        if (op == 1) {
            int tmp;
            cin >> tmp;
            pq.push(tmp);
            if (pq.size() > k) pq.pop();
        }
        else if (op == 2) {
            cout << (pq.size() == k ? pq.top() : -1) << '\n';
        }
    }

    return 0;
}
posted @ 2022-07-08 23:50  空白菌  阅读(21)  评论(0编辑  收藏  举报