樹鏈剖分用於將樹分割成若干條鏈的形式,以維護樹上路徑的資訊。
樹鏈剖分有多種形式,如重鏈剖分、長鏈剖分等,通常說的樹鏈剖分指重鏈剖分。
首先給出一些定義:
(圖源:oi-wiki)
跑兩個 dfs ,第乙個跑出來子樹大小,深度,父節點和重子節點,第二個 dfs 優先擴充套件重子節點,記錄新編號和新點權,這樣能保證先剖出來的一定是重鏈。
int hson[maxn], // 重子節點
fa[maxn], // 父節點
cnt[maxn], // 子樹大小
dep[maxn], // 深度
val[maxn], // val[i]表示初始編號i的點的點權
top[maxn], // 所在鏈的頂
id[maxn], // 新編號(dfn序)
a[maxn]; // 新編號為i的點的點權
void dfs(int u,int f)
}void dfs1(int u,int f,int t)
時間複雜度:\(o(n)\)
lca每次把重鏈頂深度較大的點向上跳重鏈,如果兩個點在同一條鏈上,就直接返回深度更小的。
int lca(int x,int y)
路徑上的點權修改
過程和求 lca 類似,由於每一條重鏈上的 dfn 值都是連續的,可以用線段樹修改,在向上跳的過程中把每條重鏈都修改了,最後修改剩餘部分。
void update_chain(int x,int y,int k)
路徑上的點權和查詢
在向上跳的時候答案加上每條重鏈的和,最後加上剩餘部分。
int query_chain(int x,int y)
樹鏈剖分學習筆記
寫 又犯了很sb的錯誤,線段樹寫錯了。好像每次都會把r l 1寫成l r 1,然後就只有20分。寫的比較醜,壓了壓之後190行。基本上是我打過的最長的乙個模板了 然後簡單介紹一下樹剖吧。樹鏈剖分,就是把樹剖分成鏈,然後用資料結構來維護這些鏈,使得詢問 修改的複雜度達到o logn o l ogn 不...
樹鏈剖分學習筆記
樹鏈剖分 mod estc oder modestcoder modest code r如果你是重兒子,你就在重路徑上。如果你是輕兒子,暴力沿著祖先向上爬最多log nlogn logn 次就可以遇到重路徑。或者到根 而樹上操作基本就是找祖先 也許有人喜歡我的碼風 include include d...
樹鏈剖分學習筆記
前言 書上只講了重鏈剖分,菜雞也只會這一種,想看其他的是別想了。要會樹鏈剖分,首先你需要了解一些概念。我們把乙個節點的所有兒子節點中子樹節點數最大的稱為重兒子,也就是size最大的子節點。size的定義我在講換根dp時說過,因此不再贅述。對於每個節點的重兒子,我們用 son x 來記錄它,父親節點到...