(之前寫過樹剖的題,但沒有完全理解,現在又無法複述思路了,所以重新學習一下,部分語句參考大神的敘述)
一、概念
樹鏈剖分,顧名思義,樹是由一根根樹鏈組成的,我們現在要來把它按鏈來分解掉。我們知道,大部分樹上的問題都是圍繞樹的路徑來做文章,分解成一條條的鏈之後,我們就可以對節點(邊)就行編號了,而同一根鏈,編號是連續的,這樣就轉化為了區間問題,我們就可以使用線段樹等姿勢來解決修改、求和、求最值等問題了(所以樹剖不是一種資料結構)。
(盜圖~~~)
二、怎樣剖分
先描述幾個概念和性質
重兒子:siz[u]為v的子節點中siz值最大的,那麼u就是v的重兒子。
輕兒子:v的其它子節點。
重邊:點v與其重兒子的連邊。
輕邊:點v與其輕兒子的連邊。
重鏈:由重邊連成的路徑。
輕鏈:輕邊。
剖分後的樹有如下性質:
性質1:如果(v,u)為輕邊,則siz[u] * 2< siz[v];
性質2:從根到某一點的路徑上輕鏈、重鏈的個數都不大於logn。
為了實現性質2,就必須要求我們剖分出輕重鏈,這個過程我們可以用兩個dfs實現,記
fa[v] v的父節點
son[v] 與v同重鏈的兒子節點
pos[v] 編號,即對應線段樹中的位置
size[v] 以v為根的子樹中節點數
top[v] v所在鏈的頂端節點
第一次dfs,尋找重邊
第二次dfs,編號
void dfs1(int x)}
void split(int x)
for(int i = h[x]; i; i = e[i].next)
split(e[i].v);
}
對於u,v兩點,求解時,我們不停將深度大的點向上走(利用top),並維護詢問,直到在同一鏈上為止。 樹鏈剖分學習
樹鏈剖分 看了學習了樹鏈剖分 適用於在樹上的路徑操作。關鍵在於重鏈的構造,把它表示到了資料結構上的連續區間,降低了複雜度。主要操作步驟實際上有三個部分 1 構造重鏈 2 如何維護資料 3 分解為輕重鏈的查詢與修改 include include include include define n 10...
樹鏈剖分學習
樹鏈剖分其實就是把一棵樹剖分成一條條鏈 重鏈輕鏈 然後用線段樹進行操作維護。複雜度logn 記錄 deep size fa pos bl 陣列 deep深度,size子樹節點個數,pos節點編號,bl所在重鏈頂端節點編號,fa父親編號。例題 bzoj1036 include define inf 1...
樹鏈剖分學習
兩次dfs,第一次處理處fa,depth,size,son,第二次處理出top,rank,id 一條重鏈的編號是連續的,可以用資料結構維護,做事情的時候判斷是否在同一條鏈上,不是就把最深的跳到鏈頭的fa,然後繼續判斷 luogu3384 模板 樹鏈剖分 區間加,求和,子樹加,求和 include i...