樹鏈剖分學習

2021-07-24 05:57:56 字數 1010 閱讀 9786

(之前寫過樹剖的題,但沒有完全理解,現在又無法複述思路了,所以重新學習一下,部分語句參考大神的敘述)

一、概念

樹鏈剖分,顧名思義,樹是由一根根樹鏈組成的,我們現在要來把它按鏈來分解掉。我們知道,大部分樹上的問題都是圍繞樹的路徑來做文章,分解成一條條的鏈之後,我們就可以對節點(邊)就行編號了,而同一根鏈,編號是連續的,這樣就轉化為了區間問題,我們就可以使用線段樹等姿勢來解決修改、求和、求最值等問題了(所以樹剖不是一種資料結構)。

(盜圖~~~)

二、怎樣剖分

先描述幾個概念和性質

重兒子: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...