【學習筆記】樹分治

Wind_Leaves_ShaDow發表於2024-12-09

點分治

普通的分治在一段子段 \([l,r]\) 中處理和 \(mid\) 有關的資訊然後遞迴處理 \([l,mid)\)\((mid,r]\)。由於中點的優秀性質這種看似暴力的做法實際複雜度是 \(O(n\log n)\) 的。

點分治是一種把分治思想運用到樹上解決問題的演算法(但是其實更多人願意稱其為資料結構?)。它一般適用於與路徑有關的問題。

考慮我們現在處理的是子樹 \(p\),僅僅根據子節點很顯然會導致分治複雜度出錯。我們希望尋找一種遞迴方式使得遞迴層數儘量地小。聯想到以樹的重心為根每個子樹大小不超過其一半的性質,每次找到一個連通塊的重心,處理經過這個重心的答案,然後把這個重心刪去遞迴其子樹。

注意我們處理的是這個重心的答案,於是我們要減去來自同一子樹的貢獻。具體的做法有很多種。你可以把 加貢獻和處理答案分開做,對於一個子樹先把它的答案統計完再加入其貢獻。這種寫法常數略大。

你也可以 記錄一個點屬於哪個子樹然後離線下來做,在本身就需要離線處理貢獻的題目裡面很好用。

如果記錄一個節點屬於哪個子樹但是不好維護其在那個子樹中的貢獻也可以把答案統計完後 用類似容斥的做法 把來自同一個子樹的貢獻減去。

點分樹

嘗試把每層找到的重心和上一層的重心連邊形成一棵點分樹。

有一些優秀的性質。

相關文章