#29150: 線段樹(沒學過演算法的新手的心得分享)


cges30901 (cges30901)

學校 : 不指定學校
編號 : 30877
來源 : [101.136.203.77]
最後登入時間 :
2024-04-07 15:34:14
d668. 奇怪的老闆 | From: [39.10.69.232] | 發表日期 : 2022-02-01 21:58

(打完之後發現寫得有點亂,可以直接看我參考的這幾個網址:
https://hackmd.io/@wiwiho/CPN-segment-tree
https://zh.wikipedia.org/wiki/%E7%B7%9A%E6%AE%B5%E6%A8%B9
https://www.geeksforgeeks.org/binary-tree-set-1-introduction/)

我是演算法新手,如果有錯誤或是有更好的方法歡迎指正。

這題如果單純把薪水存在陣列,再用for迴圈找最大最小值會TLE,所以必須用線段樹。線段樹的結構是二元樹。
分享我建立線段樹的方法,以下使用C++:
首先我先建立類別Node,裡面包含兩個子節點的指標、區間範圍、區間範圍的最大值、最小值。注意這裡子節點必須是指標,不然會無法編譯(參考資料:https://stackoverflow.com/questions/6349822/incomplete-type-in-class-which-has-a-member-of-the-same-type-of-the-class-itse)。
然後做Node的constructor。有三個參數,分別是區間左端、區間右端和薪水陣列。在constructor中,我先把區間範圍從參數中存下來,然後檢查範圍。如果範圍只包含一個數字,那麼最大值最小值就是那個數字,不需要子節點。如果不只一個數字,就呼叫兩個子節點(左和右)的constructor,左子節點的左端與本節點相同,右端是本節點(左端加右端)/2,而右子節點的左端是本節點(左端加右端)/2+1,右端與本節點相同。最後設定節點最大值是兩個子節點中較大的最大值,最小值是兩個子節點中較小的最小值。這樣子線段樹就建立好了。
最後是查詢的方式。可以建立member function來查詢,如果查詢的區間與節點相同,那就直接回傳節點的最大最小值。如果完全在查詢區間完全在其中一個子節點中,就呼叫那一個子節點的查詢函數。如果範圍分布在兩個子節點中,就兩個子節點都查詢,再比較大小。

 
ZeroJudge Forum