hihocoder 1105 題外話 堆

2022-07-12 10:18:10 字數 2922 閱讀 8581

時間限制:10000ms

單點時限:1000ms

記憶體限制:256mb

描述小ho有乙個糖果盒子,每過一段時間小ho都會將新買來的糖果放進去,同時他也會不斷的從其中挑選出最大的糖果出來吃掉,但是尋找最大的糖果不是一件非常簡單的事情,所以小ho希望能夠用計算機來他幫忙計算這個問題!

輸入每個測試點(輸入檔案)有且僅有一組測試資料。

在一組測試資料中:

第1行為1個整數n,表示需要處理的事件數目。

接下來的m行,每行描述乙個事件,且事件型別由該行的第乙個字元表示,如果為'a',表示小ho將一粒糖果放進了盒子,且接下來為乙個整數w,表示這顆糖果的重量;如果為't',表示小ho需要知道當前盒子中最重的糖果的重量是多少,在知道這個值之後,小ho會將這顆糖果從盒子中取出並吃掉。

對於100%的資料,滿足1<=n<=10^5, 1<=w<=10^5。<>

對於100%的資料,滿足沒有2顆糖果的重量是相同的,最開始的時候小ho的糖果盒子是空的,且每次小ho想要取出一顆糖果的時候盒子裡一定至少有一顆糖果。

輸出在一組測試資料中:

對於每個型別為't'的時間,輸出1個整數w_max,表示在這一時刻,盒子中最重的糖果的重量。

樣例輸入

5

a 77751

a 1329

a 26239

a 80317

t

樣例輸出

80317

小ho寫了半天的brute force演算法,卻發現自己的電腦效能還是差了一點,不能滿足其滔天食慾,於是乖乖的找上了小hi,請教有沒有更為高效的演算法。

「正好,本來想要給你講解的prim演算法的優化需要用到堆結構,既然你也遇到了這樣乙個非常適合使用堆來解決的問題,那就一併講解給你聽吧!」小hi滿意的點了點頭。

「堆……那是什麼東西啊?」小ho問道。

「堆有兩種,小根堆和大根堆,先說大根堆,如果對於乙個節點上帶有權值的完全二叉樹,每個節點的權值都比它的左右子節點的權值大的話,這顆二叉樹就被稱為大根堆。」小hi道。

「那麼小根堆應該就是每個節點的權值都比它的左右子節點的權值小咯?」小ho得出結論。

「是的!」小hi說道:「那麼如果我們把每個節點都看做一棵糖果,整棵樹看成你的糖果盒子,那麼想要找到最大的糖果其實非常簡單——就是這棵樹的根節點!」

「每個節點的權值都比它的左右子節點的權值大……那麼根節點自然是權值最大的節點。」小ho想了想道:「沒有錯,但是問題在於,我怎麼樣構造這樣一棵樹呢?」

「我們這樣來考慮:如果現在所有的糖果已經被構造成為了這樣一棵樹,你往其中放入一棵新的糖果,該如何保持這棵樹的性質?」小hi問道。

小ho邊思考邊道:「唔……首先我得把它當做乙個節點加入到樹中——為了保持仍然是完全二叉樹,只能加到最後一排的第乙個空餘位置(如果最後一排滿了則加到新的一排的第乙個位置),然後我們考慮可能出現違反大根堆性質的地方:新加入節點p的權值可能比其父親節點f的權值要大,但是解決方法很簡單:直接將p和f的位置進行交換(在實際操作中直接將權值進行交換就可以了),但是這樣可能會導致f的權值比其父親節點f'要大,所以這樣的交換需要一直向上進行,直到某個節點的權值不再比其父親節點要大,或者到達了根節點。總而言之,就是在加入乙個新的節點之後,不斷向上消除不符合大根堆性質的地方。」

「嗯~這樣是正確的!」小hi點了點頭:「這樣新增一顆新糖果的問題得到了解決,但是拿掉一棵糖果的問題你準備怎麼解決呢?」

「拿掉的糖果是根節點……這樣會很麻煩,不如先將根節點與最後一層最後乙個節點進行對調,這樣仍然保證了是一棵完全二叉樹,所以問題還是如何保證『每個節點的權值都比它的左右子節點的權值大』這個性質。現在可能產生問題的節點只有根節點,所以考察根節點t和其左右子結點l、r的權值大小關係,不妨設l的權值比r要大(反之會有相似的結論),如果l的權值比t小,那麼不存在任何問題,否則將l和t的權值進行交換便可以解決根節點處不滿足性質的問題——但是這樣的交換又可能導致l(現在的權值是t的權值)不滿足這樣的情況,所以便要繼續向下進行檢查,知道某個節點的權值比其左右子節點都要大,或者到達了葉子節點。總而言之,就是將根節點同最後乙個節點互換並刪除之後,從根節點開始不斷向下消除不符合大根堆性質的地方。」

小hi點了點頭道:「這樣一來,對於兩種操作,你都可以維護好大根堆的性質,而最開始的狀態——一棵為空的樹自然也是滿足這個性質的,所以這個問題不就變得很簡單了麼!」

「是的!」小ho高興道:「我可以去吃糖了!」

分析:方法一:用c++的stl中優先佇列,priority_queue.

1 #include 2 #include 3

using

namespace

std;

4int

main() else

if (c == 't'

) 18}19

return0;

20 }

方法二:自己建立乙個大根堆。用一維陣列

1 #include 2 #include 3

using

namespace

std;45

int heap[100005], size = 0;6

//第乙個元素的下標為1.

7void push(int

x)16 heap[i] =x;17}

1819

intpop()

34 heap[i] =x;

3536

return

ret;37}

3839

intmain() else51}

52return0;

53 }

開篇 題外話

大學畢業後進入河北省某公司從最基本的資料錄入員開始做起,然後一步一步提公升,最後到管理層。五年半的時間收穫很多,主要有如下幾方面。1 了解了資料採集到資料處理的整個流程可使用的方案,並最終確定最優方案,以及如何保證資料錄入的高質量方案。2 如何可以獲得甲方高度的信任 因情況特殊,工作地點由甲方提供 ...

比賽及題外話

一直覺得大學的比賽多數以興趣為主,只是有時候會發現,對於學生是如此,但是對於學校並非如此。對於學校來說,他們所需要的只是在比賽中拿個好的名次,所以會鼓勵學生去做,這個是一種自上而下的習慣。我們的奧運會是如此,我們所鼓勵的是一種民族主義,而不是個人主義。我們在比賽中所扮演的角色對於老師來說都是可被替代...

題外話 學習演算法再出發

題外話 作為乙個生信入門級的新手,我一直對演算法心馳神往,希望有朝一日能成為高手。可是多少次在學習演算法的路上我都半途而廢,時常感慨於 道阻且長 阻礙我的不僅有對遠方艱辛的畏懼,還有對腳下羈絆的無奈困惑。怎麼說呢,對遠方艱辛的畏懼很大程度上源於自己急於求成的焦慮心態。面對浩如煙海的演算法,不免會 望...