很巧妙的一个题,自己没想出来。
用一个「对顶堆」来维护,即一个大根堆和一个小根堆。保证大根堆的队首 \(\le\) 小根堆的队首,并使他们的堆中元素的个数尽量相等。
操作如下:
- 每次加入一个元素时,如果这个数比大根堆的队首大,就加入小根堆;否则加入大根堆。
- 比较两个堆中的元素个数。如果差值 \(> 1\),将元素个数多的那堆的队首弹出,并加入到个数少的那堆,直到元素个数差值 \(\le 1\)。
- 如果两堆的元素个数的差值为 \(1\),输出元素个数多的那堆的队首即可。
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
const int N = 100010;
int n, a[N];
priority_queue<int> q1;
priority_queue<int, vector<int>, greater<int> >q2;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int t; scanf("%d", &t);
// printf("%d\n", t);
if (q1.empty()) q1.push(t);
else if (q1.top() >= t) q1.push(t);
else q2.push(t);
while (int(q1.size() - q2.size()) > 1) {
int tmp = q1.top();
q1.pop();
q2.push(tmp);
}
while (int(q2.size() - q1.size()) > 1) {
int tmp = q2.top();
q2.pop();
q1.push(tmp);
}
if (q2.size() > q1.size()) printf("%d\n", q2.top());
else if (q1.size() > q2.size()) printf("%d\n", q1.top());
}
return 0;
}
调了大概 25min,因为 q1.size() - q2.size()
有精度问题。(我服了这都能出 bug)