安利一个黑科技,不知道是谁发明的(好像也有些年代了?)
其实这个黑科技的本质就是一个大根堆,不同的是 它支持删除堆内任意元素,同时也支持堆的基本操作
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();}
};
结构介绍
解释一下两个堆 (q1) 和 (q2) :
q1
(q1) 存储了当前所有元素(包括未删除元素)
q2
(q2) 存储了 (q1) 中已删除的元素
操作介绍
push
我们看到 push 操作,很平常,就是向 (q1) 中 (push) 一个新的元素
erase
这就是这个黑科技的精华了,我们向 (q2) 中 (push) 一个元素表示在 (q1) 中它已经被删除了
pop
这里就要用到 (q2) 里面的元素了,如果堆顶的元素已经被 (erase) 过,那么它此时应该在 (q2) 中的堆顶
此时我们把两个堆一起 (pop) 就好了,直到堆顶元素不同或者 (q2) 没元素了
top
这里就是先进行和 (pop) 中类似的操作,删除已经 (erase) 的元素,然后取出堆顶
top2
有点骚,这个操作可以取出堆中的次大值,而 (top3) 、(top4) 以此类推(虽说不怎么用到)
size
这个就是返回堆大小的,可以知道堆当前真实大小就是 (q1) 大小减去 (q2) 大小
总结
新技能 (get) !
但是注意一下,这里我们的 (erase) 操作必须合法, 否则会出现 (bug)
或者修改一下操作可能可以支持不合法操作...但我本人觉得不大可能...