樹上啟發式合併(dsu on tree)學習筆記【理解+模板+例題】

Qingo呀發表於2020-11-20

一、理解

先從一個典型的例題開始,樹的每個節點都有一個顏色,求某個節點v的子樹中顏色c的個數。暴力的話,就是對於每一個節點都統計一下子樹中顏色c的個數,複雜度為O( N^{2})。現在,我們來優化。可以發現我們做了很多重複的工作,如果能利用一些工作的結果那就好了。這裡要引入輕/重兒子的思想(好像就是輕重鏈,樹鏈剖分。。。。),可以證明從整棵樹的根節點到樹中任意一點的路徑上最多有 logN 條輕邊(相關定義及證明請參考部落格:https://www.cnblogs.com/zwfymqz/p/9683124.html)。所以我們把重兒子的貢獻儲存,每次暴力計算輕兒子以及自己的貢獻即可。每個輕兒子最多會被暴力列舉logN次,所以時間複雜度為O(NlogN)

二、模板

基本套路就是,對於u的子樹:

1、計算所有輕兒子v的答案,不儲存。

2、計算重兒子son[u]的答案,並儲存貢獻。

3、暴力計算本節點u及所有輕兒子v對答案的貢獻。

4、加上重兒子son[u]的貢獻,得到該子樹u的答案。

5、如果u不是其父親的重兒子,即不需要儲存貢獻,清除其子樹的貢獻。

這種題一定要轉化為考慮每個節點的子樹對答案的影響,如果是詢問就轉化為對子樹的詢問。

三、例題

1、CF 600E Lomsat gelral      題解

2、CF 570D Tree Requests    題解

3、SGU 507 Treediff               題解

特推部落格:https://codeforces.com/blog/entry/44351

相關文章