Loading

「学习笔记」对顶堆

介绍

对顶堆是由两个堆来维护的数据结构,两个堆一个是较大数的小根堆,一个是较小数的大根堆,可以动态维护第 \(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;
}
posted @ 2022-08-28 10:13  yi_fan0305  阅读(89)  评论(0编辑  收藏  举报