【每日一题】12.Running Median (对顶堆)
补题链接:Here
题意:动态的维护中位数的问题,依次读入一个整数,每当总个数为奇数时输出此时序列的中位数
使用对顶堆的在线做法。
为了实时找到中位数,我们可以建议两个二叉堆:一个小根堆、一个大根堆。在依次读入数字的过程设当前序列长度为
- 序列中从小到大排名为
~ 的整数存储在大根堆中; - 序列中从小到大排名为
~ 的整数存储在小根堆中。
任何时候如果某一个堆中元素过多则是打破了平衡需要取出该堆的堆顶插入到另一个堆。这样一来序列的中位数就是小根堆的堆顶
关于新数
上述算法就是 “对顶堆” 算法
这个代码会爆空间,但很好的实现的上述过程
priority_queue<int> q1, q2;
void solve() {
while (q1.size()) q1.pop();
while (q2.size()) q2.pop();
int num, n;
cin >> num >> n;
cout << num << " " << (n + 1) / 2 << "\n";
int a;
cin >> a;
cout << a << " ";
q2.push(-a);
int cnt = 1;
for (int i = 2; i <= n; ++i) {
cin >> a;
if (a < -q2.top()) q1.push(a);
else
q2.push(-a);
int s = q1.size();
if (s > i / 2) {
q2.push(-q1.top());
q1.pop();
}
if (s < i / 2) {
q1.push(-q2.top());
q2.pop();
}
if (i & 1) {
cout << -q2.top() << " ";
if (++cnt % 10 == 0) cout << endl;
}
}
cout << "\n";
}
AC 代码
vector<short> a;
void solve() {
a.clear();
int k, n;
cin >> k >> n;
cout << k << " " << (n + 1) / 2 << "\n";
for (int i = 1; i <= n; ++i) {
short x;
cin >> x;
a.insert(upper_bound(a.begin(), a.end(), x), x);
if (i & 1) cout << a[(i - 1) / 2] << " ";
if (i % 20 == 0) cout << "\n";
}
cout << "\n";
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· 分享4款.NET开源、免费、实用的商城系统
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 全程不用写代码,我用AI程序员写了一个飞机大战