可删除堆
定义:
也是属于对朴素堆的一种应用
一个不同于 朴素堆只可以删除堆顶的 可删除堆,它可任意元素进行删除。
为了保证可以 任意删除 元素,可删除堆是通过
构建两个堆,一个堆维护存放在堆中的元素,另一个堆维护应该被删除的元素。
为了方便称呼,我们称 维护存放在堆中的元素的堆 为原堆,堆维护应该被删除的元素的堆 为删堆。
原理呢,因为在使用堆的过程中,往往是去一个集合的最大值和最小值,然鹅要删除的元素对当前的最大值(或最小值)并无影响。由于 朴素堆 只能满足删除堆顶元素,那么只有当 应该已删除的元素 位于堆顶的时候,才会影响答案。那就先把 删除的元素 放入另一个相似的堆里,作为标记。
当 原堆的堆顶 为 要删的元素 时, 另一个堆的堆顶也一定是这个元素,那么就可以愉快地删掉啦!
操作:
-
#插入Insert:
将要插入的元素push进原堆里,即
void insert(int x) {q1.push(x); }
-
#删除Delete:
将要删除的元素push进删堆里,而不动 原堆 即
void del(int x) {q2.push(x);}
-
#查询get:
假设我们要得到 某些数的最大值,即大根堆。
我们要在原堆中 取出堆顶元素,但是可能这个堆顶元素已经被删除了,也就是入了删堆。
此时可以想到,原堆的最大值和删堆的最大值一定都是堆顶,且相同。
所以我们开始pop两个堆,也就是真真正正的删掉了这个元素
int get() {
while(!q2.empty()&&!q1.empty()&&q2.top()==q1.top())
q1.pop(), q2.pop();
return q1.top();
}
代码
【可删除堆のCode】
struct Heap {// 可删除堆
priority_queue<ll, vector<ll>, greater<ll> > q1, q2;
// q1 维护存放在堆中的元素的堆,即原堆
// q2 维护应该被删除的元素的堆,即删堆。
void insert(int x) {
//插入Insert:将要插入的元素push进原堆里
q1.push(x);
}
void del(int x) {
//删除Delete:将要删除的元素push进删堆里,而不动 原堆
q2.push(x);
}
int get() {//查询get
while(!q2.empty()&&!q1.empty()&&q2.top()==q1.top()) {
q1.pop(), q2.pop();
}
return q1.top();
}
} heap;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】