前言
AtCoder 竟然出了原题!
建议评黄。
如果你挑战完了这道题,双倍经验在这里。(This is 原题)
思路
由于题目是要我们求中位数,很显然需要排序。
可是每次都排一次序显然会超时,所以我们需要考虑更优的解法。
由于是中位数,所以可以把他单独存起来,然后不难发现你需要维护左右两边。
然后你需要实现一个 a d d add add 函数添加一个数。具体实现需要 2 2 2 个优先队列,其中 l l l 是大根堆, r r r 是小根堆。
第一步,比较新数和原中位数,若较小,则压入 l l l,否则压入 r r r。
第二步,比较左右两个优先队列的大小,多贴少补。
为了实现容易,可以选择把中位数存在 l l l 或 r r r 中的某一个里面,我选择了 l l l。
实际上存那个都无所谓,因为你 pop 之后中位数都会第一个弹出来。
流程
- 把最初的 x x x 添加进去
- 把 a , b a,b a,b 读入并压进去
- 把 l l l 或 r r r 的队首输出,这取决于你把中位数存在哪个队列里面。
时间复杂度 O ( Q log Q ) \mathcal O(Q \log Q) O(QlogQ),可以通过。
代码
cpp
#include <bits/stdc++.h>
#define int long long
using namespace std;
priority_queue<int> l;
priority_queue<int, vector<int>, greater<int> > r;
void add(int x) {
if (l.empty() || x <= l.top()) l.push(x);
else r.push(x);
if (l.size() > r.size() + 1) {
r.push(l.top());
l.pop();
}
if (r.size() > l.size()) {
l.push(r.top());
r.pop();
}
}
signed main() {
cin.tie(0) -> sync_with_stdio(0);
int x, q; cin >> x >> q;
while (!l.empty()) l.pop();
while (!r.empty()) r.pop();
add(x);
while (q--) {
int a, b; cin >> a >> b;
add(a); add(b);
cout << l.top() <<'\n';
}
return 0;
}
记得三连哦~