支持删除任意元素以及一些其余基本操做的堆

安利一个黑科技,不知道是谁发明的(好像也有些年代了?)spa

其实这个黑科技的本质就是一个大根堆,不一样的是 它支持删除堆内任意元素,同时也支持堆的基本操做code

code

代码以下:get

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\)it

q1

\(q1\) 存储了当前全部元素(包括未删除元素)io

q2

\(q2\) 存储了 \(q1\) 中已删除的元素class

操做介绍

push

咱们看到 push 操做,很日常,就是向 \(q1\)\(push\) 一个新的元素bug

erase

这就是这个黑科技的精华了,咱们向 \(q2\)\(push\) 一个元素表示在 \(q1\) 中它已经被删除了queue

pop

这里就要用到 \(q2\) 里面的元素了,若是堆顶的元素已经被 \(erase\) 过,那么它此时应该在 \(q2\) 中的堆顶总结

此时咱们把两个堆一块儿 \(pop\) 就行了,直到堆顶元素不一样或者 \(q2\) 没元素了top

top

这里就是先进行和 \(pop\) 中相似的操做,删除已经 \(erase\) 的元素,而后取出堆顶

top2

有点骚,这个操做能够取出堆中的次大值,而 \(top3\)\(top4\) 以此类推(虽然说不怎么用到)

size

这个就是返回堆大小的,能够知道堆当前真实大小就是 \(q1\) 大小减去 \(q2\) 大小

总结

新技能 \(get\)

可是注意一下,这里咱们的 \(erase\) 操做必须合法, 不然会出现 \(bug\)

或者修改一下操做可能能够支持不合法操做...但我本人以为不大可能...

相关文章
相关标签/搜索