簡單理解樹上差分(點,邊)
關於樹上差分,我在這推薦一道題目poj 3417 。
題目翻譯:
樹上差分用來解決點的覆蓋或者邊的覆蓋的問題,需分別運用點的差分或者邊的差分。
先從例題入手:
給定點數為n,邊數為n-1的樹(無向邊且無重邊),先有m條連線a,b的非樹邊,求每條「樹邊」被「非樹邊」覆蓋了多少次?
邊的差分:
先設乙個f【x】,是乙個差分陣列,表示從x到x的父親的邊被覆蓋的次數。對於每一次輸入的a , b,樸素演算法是o(n)的去遍歷每一條邊,這樣的時間複雜度太高了,我們就可以用差分的思想去優化,就是樹上差分,即f[a]++,f[b]++,f[lca(a,b)]-=2;
從x到x的父親的邊被覆蓋的次數就是x的子樹和了,字首和的思想。
再來一道例題:
給定點數為n,邊數為n-1的樹(無向邊且無重邊),先有m條連線a,b的非樹邊,求每個「點」被「非樹邊」覆蓋了多少次?
不難看出,這道題只是把「樹邊」改成了「點」。
點的差分:
設f【x】為x被覆蓋的次數。修改f【x】的時候也要變化,還是輸入a,b。修改的操作為f[a]++,f[b]++,f[lca(a,b)]--,f[father[lca(a,b)][0]]--;最後乙個是lca(a,b)的父親。同樣,x的子樹和就是x點被覆蓋的次數。求每個點的子樹和只需要dfs一次,複雜度是o(nlogn)的。
實在不理解可以舉2個例子模擬一下:
1.從a到b。a,b均不是lca(a,b)。
2.從a到b。a,b其中之一為lca(a,b)。
總結一下:樹上差分用來解決「點的覆蓋」或者「邊的覆蓋」的問題,是樸素的直接遍歷演算法的優化,將樸素演算法覆蓋的時間複雜度o(n*m),直接優化為o(n),時間複雜度十分優秀。
樹上差分的兩種形式(相遇 or 行程的交集 題解)
emm,這很noip.寫這個的原因是今天考試乙個sb差分樹題居然槓了個樹剖上去,殺雞用了牛刀。而且不止一次了.總是想不到子樹和這種差分,淦 anyway,簡單寫寫吧。三重封裝 轉化後的問題都能用dfs序 樹狀陣列解決。在上文 中,樹狀陣列用bit封裝,st,ed是dfs序 本質 在序列上,字首和 字...
單例的兩種實現形式模式
1.實現形式一 單例模式 懶漢式 程式執行過程需要這個類的物件時在例項化該類的物件 author sageparadise public class singleton public static synchronized singleton getsingletoninstance return ...
模板 鍊錶的兩種實現形式
摘自李煜東 演算法競賽高階指南 鍊錶模板1 struct node node head,tail void initialize 建新鍊錶 void insert node p,int val 在p後插入包含資料val的新節點 void remove node p 刪除p void recycle ...