「学习笔记」对顶堆
介绍
对顶堆是由两个堆来维护的数据结构,两个堆一个是较大数的小根堆,一个是较小数的大根堆,可以动态维护第 \(K\) 大的值
原理
在对顶堆中,要保证小根堆的所有数始终比大根堆大,两个队中的元素进行转移时,将堆顶插入到另一个堆中,将堆顶弹出。
可以用元素转移来维护堆内的元素个数
代码
定义
priority_queue<ll> q1;
priority_queue<ll, vector<ll>, greater<ll> > q2;
转移
q2.push(q1.top());
q1.pop();
或者是
q1.push(q2.top());
q2.pop();
来道例题
P1168中位数
是一道很简单也很基础的对顶堆 虽然用 vector 可以简洁清晰的水过吧
代码:
#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
typedef long long ll;
using namespace std;
int n;
priority_queue<ll> q1;
priority_queue<ll, vector<ll>, greater<ll> > q2;
inline ll read() {
ll x = 0;
int fg = 0;
char ch = getchar();
while(ch < '0' || ch > '9') {
fg |= (ch == '-');
ch = getchar();
}
while(ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
return fg ? ~x + 1 : x;
}
int main() {
n = read();
q1.push(read());
printf("%lld\n", q1.top());
for(int i = 2; i <= n; ++i) {
ll val = read();
if(val > q1.top()) q2.push(val);
else q1.push(val);
int siz1 = q1.size(), siz2 = q2.size();
while(abs(siz1 - siz2) > 1) {
if(q1.size() > q2.size()) {
q2.push(q1.top());
q1.pop();
}
else {
q1.push(q2.top());
q2.pop();
}
siz1 = q1.size(), siz2 = q2.size();
}
if(i & 1) printf("%lld\n", siz1 > siz2 ? q1.top() : q2.top());
}
return 0;
}
朝气蓬勃 后生可畏