樹鏈剖分詳解

2021-07-23 13:00:54 字數 2744 閱讀 8081

樹鏈剖分定義

只是把一棵樹拆成鏈來處理而已,即將樹上的某些段一起通過資料結構優化進行處理來降低複雜度。

樹鏈剖分相關定義

重兒子:ve

[v] 為

u 的子節點中ve

值最大的,那麼

v 就是

u的重兒子(將子樹中最長的那一條鏈一起處理來降低複雜度)。

輕兒子:

u 除了重兒子的其它子節點。

重邊:點

u與其重兒子的連邊。

輕邊:點

u 與其輕兒子的連邊。

重鏈:由重邊連成的路徑。

輕鏈:輕邊。

樹鏈剖分基本性質

如果(v

,u)為輕邊,則ve

[u]×2[v

] ;

從根到某一點的路徑上輕鏈、重鏈的個數都不大於logn。

樹鏈剖分獨特之處
主要針對路徑進行處理,我們平時處理一顆樹的路徑的方案一般就是求解lc

a o(

nlog

n)構建,o(

logn

) 進行查詢,比如一般的求解路徑上的最大邊權,點權之類的一般lca倍增法都可以解決,如果再離線一下,或許複雜度更低。

但是樹鏈剖分的獨特之處就是可以對路徑進行修改,一般結合線段樹進行處理,查詢更新的複雜度就是o(

logn

)

樹鏈剖分理解

拿求解一條路徑上的最大值做例子,樹鏈剖分的思想就是,先對路徑進行預處理,將路徑上的資料分為幾段,然後再對這幾段求最大值,有點像分桶法。

看下圖:

比如我們要求解從頂點

11 到頂點

14 路徑上邊權的最大值,我們可以求出1−

4−9−

13−14 這條路徑上的最大值s1

,然後求出1−

2 路徑上的最大值s2

,然後再求出2−

6−11 路徑上的最大值s3

。然後我們再求解ma

x(s1

,s2,

s3) 的值就可以得到結果

[ 黑色的路徑表示圖中黑色的路徑,代表著重兒子,藍色的則是代表著不是重兒子的路徑]

從圖上我們可以看出,重兒子所在的路徑是子樹中路徑最長的,這也是為什麼重兒子的定義是子樹中節點最多的子節點,然後我們也發現黑色的路徑上的藍色編號是連續的,這是為了將這個長的路徑儲存在一段連續的區間,那麼我就可以了對這塊連續區間進行操作了。

也許大家已經想到了這樣規定的好處,因為越長的,我就一起處理,效率自然是越高了,重兒子就是這麼規定而來的。

然後我們對於區間求最值有很多方法,線段樹一般就是最優的。

相關陣列定義

de

ep[u

]:來儲存當前節點

u 的深度fa

[u]:

用來儲存當前節點

u 的父親ve

[u]:

用來儲存以

u 為根的子樹節點個數so

n[u]

:用來儲存當前節點

u 的重兒子to

p[u]

:用來儲存當前節點

u 的所在鏈的頂端節點p[

u]:用來儲存當前節點u

fp:用來儲存線段樹相應位置儲存的是當前哪個節點

模板**dfs1

void dfs1(int u, int pre, int d) }}

第乙個df

s1是為了找重邊,記錄下所有的重邊以及相關關係

模板**dfs2

void dfs2(int u, int sp) 

}

第二個dfs2就是為了連線重邊形成重鏈,即將這條長路徑給連線起來,具體步驟:以根節點為起點,沿著重邊向下拓展,拉成重鏈,不在當前重鏈上的節點,都以該節點為起點向下重新拉一條重鏈。

到此,樹鏈剖分部分完畢,構造的每條重鏈相當於一段連續的區間,然後就是用資料結構處理資料

[ 一般是線段樹處理]。

如何沿著路徑進行處理(以查詢最大值為例)

步驟跟在求解

11 到

14 的最大值一樣。

int find(int u, int v)  

tmp = max(tmp, query(1, p[f1], p[u]));

u = fa[f1];

f1 = top[u];

}if(u == v)return tmp;

if(deep[u] > deep[v]) swap(u, v);

return

max(tmp, query(1, p[son[u]], p[v]));

}

分析:

如果u與v在同一條重鏈上,那麼就直接修改了,因為他們是連續的

如果不在一條重鏈上,則往一條重鏈上靠攏,然後就會程式設計一條重鏈 [

有些地方不一定說得很清楚,希望大家指出,謝謝!]

詳解樹鏈剖分

樹鏈剖分,顧名思義為將鏈剖開分成多條。當我們想要修改樹上一條路的值或求值時,我們暴力只能用乙個個修改,這是非常慢的。這時,我們就要想乙個辦法,資料結構?但是資料結構我們都需要連續修改,可是樹上路徑的編號是不連續的。於是我們想了乙個辦法。我們先定義 fa x 為x的父親 dep x 為x的深度 siz...

樹鏈剖分詳解

重兒子 對於每乙個非葉子節點,它的兒子中 以那個兒子為根的子樹節點數最大的兒子 為該節點的重兒子 ps 感謝 shzr大佬指出我此句話的表達不嚴謹qwq,已修改 輕兒子 對於每乙個非葉子節點,它的兒子中 非重兒子 的剩下所有兒子即為輕兒子 葉子節點沒有重兒子也沒有輕兒子 因為它沒有兒子。重邊 乙個父...

樹鏈剖分詳解

樹鏈剖分,說白了就是一種讓你 不得不強行增加1k的資料結構 dms 個人理解 1 joy 證明出題人非常毒瘤 可以非常友 bao 好 li 的解決一些樹上問題 grimacing 樹鏈剖分的思想比較神奇 它的思想是 把一棵樹拆成若干個不相交的鏈,然後用一些資料結構去維護這些鏈 那麼問題來了 首先明確...