代码1:转载于https://blog.youkuaiyun.com/weixin_45630722/article/details/108286961
struct heap {//手写实现删除任意位置数值的堆 //Bq2q2 存储了 q1q1 中已删除的元素 |
代码2(转载于https://www.cnblogs.com/Judge/p/10557516.html)
支持删除任意元素以及一些其他基本操作的堆
阅读目录(Content)
安利一个黑科技,不知道是谁发明的(好像也有些年代了?)
其实这个黑科技的本质就是一个大根堆,不同的是 它支持删除堆内任意元素,同时也支持堆的基本操作
code
代码如下:
struct Heap{ priority_queue<int> q1,q2;
inline void push(int x){q1.push(x);}
inline void erase(int x){q2.push(x);}
inline void pop(){for(;q2.size()&&q1.top()==q2.top();q1.pop(),q2.pop());if(q1.size())q1.pop();}
inline int top(){for(;q2.size()&&q1.top()==q2.top();q1.pop(),q2.pop());return q1.top();}
inline int top2(){int val,ret; val=top(),pop(),ret=top(),push(val); return ret;}
inline int size(){return q1.size()-q2.size();}
};
结构介绍
解释一下两个堆 q1q1 和 q2q2 :
q1
q1q1 存储了当前所有元素(包括未删除元素)
q2
q2q2 存储了 q1q1 中已删除的元素
操作介绍
push
我们看到 push 操作,很平常,就是向 q1q1 中 pushpush 一个新的元素
erase
这就是这个黑科技的精华了,我们向 q2q2 中 pushpush 一个元素表示在 q1q1 中它已经被删除了
pop
这里就要用到 q2q2 里面的元素了,如果堆顶的元素已经被 eraseerase 过,那么它此时应该在 q2q2 中的堆顶
此时我们把两个堆一起 poppop 就好了,直到堆顶元素不同或者 q2q2 没元素了
top
这里就是先进行和 poppop 中类似的操作,删除已经 eraseerase 的元素,然后取出堆顶
top2
有点骚,这个操作可以取出堆中的次大值,而 top3top3 、top4top4 以此类推(虽说不怎么用到)
size
这个就是返回堆大小的,可以知道堆当前真实大小就是 q1q1 大小减去 q2q2 大小
总结
新技能 getget !
但是注意一下,这里我们的 eraseerase 操作必须合法, 否则会出现 bugbug
或者修改一下操作可能可以支持不合法操作...但我本人觉得不大可能...