1. 程式人生 > >支持刪除任意元素以及一些其他基本操作的堆

支持刪除任意元素以及一些其他基本操作的堆

包括 pan 以及 inline pop 除了 line truct 基本

一個黑科技,不知道是誰發明的(好像也有些年代了?)

其實這個黑科技的本質就是一個大根堆,不同的是 它支持刪除堆內任意元素,同時也支持堆的基本操作

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

或者修改一下操作可能可以支持不合法操作...但我本人覺得不大可能...

支持刪除任意元素以及一些其他基本操作的堆