题目链接: P1801 黑匣子
题目大意
题目描述的已经够清楚了, 我就不说了自己读吧
solution
哇, 查询区间第 (k) 大诶, 平衡树~
写平衡树的话, 觉得有点大材小用了, 那我们用什么做呢?
堆+贪心!
那我们怎么贪呢? 我们的贪心思路是什么呢?
我们维护两个堆, 一个大根堆维护小于第 (k) 小的值的元素, 一个小根堆维护大于等于第 (k) 小的值的元素
我们怎么判断是第 (k) 小呢, 大根堆的 (size+1) 就是第 (k) 小每次放元素的时候判断一下就可以了
但是会不会有细节问题呢? 那啃腚是有的自己验证吧
code:
/**
* Author: Alieme
* Data: 2020.8.26
* Problem: Luogu P1801
* Time: O(nlogn)
*/
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#define ll long long
#define rr register
#define inf 1e9
#define MAXN 500010
using namespace std;
inline int read() {
int s = 0, f = 0;
char ch = getchar();
while (!isdigit(ch)) f |= ch == '-', ch = getchar();
while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
return f ? -s : s;
}
void print(int x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) print(x / 10);
putchar(x % 10 + 48);
}
priority_queue<int> q;
priority_queue<int, vector<int>, greater<int> >p;
int n, m, last;
int a[MAXN];
signed main() {
n = read();
m = read();
for (rr int i = 1; i <= n; i++) a[i] = read();
for (rr int i = 1; i <= m; i++) {
int u = read();
for (rr int j = last + 1; j <= u; j++) {
q.push(a[j]);
if (q.size() == i) p.push(q.top()), q.pop();
}
cout << p.top() << "
";
q.push(p.top());
p.pop();
last = u;
}
}