树上启发式合并
文章內(nèi)容選自O(shè)I Wiki
參考博客
內(nèi)容:
樹上啟發(fā)式合并(dsu on tree)對(duì)于某些樹上離線問題可以速度大于等于大部分算法且更易于理解和實(shí)現(xiàn)的算法。
他是用來(lái)解決一類樹上詢問問題,一般這種問題有兩個(gè)特征:
一般就可以簽上dsu on tree
例題:
給出一棵 n個(gè)節(jié)點(diǎn)以 1為根的樹,節(jié)點(diǎn) u的顏色為cu ,現(xiàn)在對(duì)于每個(gè)結(jié)點(diǎn) u詢問 u子樹里一共出現(xiàn)了多少種不同的顏色。
n<=2e5
樹套樹可以解決,如果可以離線的話,樹上莫隊(duì)復(fù)雜度帶根號(hào),現(xiàn)在我們要用一個(gè)帶log的算法。
對(duì)于直接暴力復(fù)雜度為O(n^2),即對(duì)每一個(gè)子節(jié)點(diǎn)進(jìn)行一次遍歷,
對(duì)于每個(gè)節(jié)點(diǎn)的答案是由其子樹和其本身得到的,現(xiàn)在考慮利用這個(gè)性質(zhì)處理問題
我們預(yù)處理出每個(gè)節(jié)點(diǎn)子樹的大小和其重兒子,重兒子同樹鏈剖分一樣,都是擁有節(jié)點(diǎn)最多子樹的兒子,這個(gè)過(guò)程O(n)求
用cnt[i]表示顏色i出現(xiàn)的次數(shù),ans[u]表示節(jié)點(diǎn)u的答案
對(duì)于一個(gè)節(jié)點(diǎn)u,我們按以下步驟遍歷:
3. 先遍歷u的輕(非重)兒子,并計(jì)算答案,但不保留遍歷后對(duì)cnt數(shù)組的影響(消除遞歸產(chǎn)生的影響)
4. 遍歷重兒子,保留對(duì)cnt的影響(不消除遞歸的影響)
5. 再遍歷u的輕兒子的子樹節(jié)點(diǎn),加入這些結(jié)點(diǎn)的貢獻(xiàn),得到u的答案
對(duì)于一個(gè)節(jié)點(diǎn),我們遍歷一次重兒子,兩次非重兒子,最劃算
為什么不合并第一步和第三步呢,因?yàn)閏nt數(shù)組不能重復(fù)使用,不然空間復(fù)雜度太高,需要O(n)內(nèi)完成
若一個(gè)節(jié)點(diǎn)u被遍歷了x次,則其重兒子被遍歷x次,輕兒子被遍歷2x次
這樣的復(fù)雜度是O(nlog n)
證明:
性質(zhì):一個(gè)節(jié)點(diǎn)到根的路徑上輕邊個(gè)數(shù)不會(huì)超過(guò)logn條
我們考慮一個(gè)點(diǎn)會(huì)被訪問幾次?
一個(gè)點(diǎn)被訪問只有兩種情況:
如果統(tǒng)計(jì)一個(gè)點(diǎn)的貢獻(xiàn)的復(fù)雜度為O(1)的話,該算法的復(fù)雜度為O(nlogn)
應(yīng)用
可以水一些樹套樹的題,也可以把樹上莫隊(duì)O(n√m)吊打
例題:
CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
CF600E Lomsat gelral
CF570D Tree Requests
CF208E Blood Cousins
CF246E Blood Cousins Return
CF1009F Dominant Indices
CF375D Tree and Queries
總結(jié)
- 上一篇: 感冒可以健身吗
- 下一篇: Tree Xor(未完全搞定)