樹鏈剖分(輕重樹)模板

2021-10-05 04:14:40 字數 2181 閱讀 1371

例題

樹鏈剖分就是用兩個dfs重新給樹編號、深度、求父節點、求重兒子、子樹大小、每條重鏈的頂端,然後用線段樹維護新的編號的樹

#include

#include

using

namespace std;

#define n 200010

int n,m,r,mod;

int head[n]

,nex[n]

,e[n]

,w[n]

,tot;

int dep[n]

,fa[n]

,siz[n]

,son[n]

,id[n]

,wt[n]

,top[n]

;int cnt,res;

struct treet[n*4]

;void

add(

int x,

int y)

void

push

(int p)

void

build

(int p,

int l,

int r)

int mid = l+r>>1;

build(2

*p,l,mid)

;build(2

*p+1

,mid+

1,r)

; t[p]

.sum=

(t[2

*p].sum+t[

2*p+1]

.sum)

%mod;

}void

update

(int p,

int l,

int r,

int k)

int mid =t[p]

.l+t[p]

.r>>1;

push

(p);

if(l<=mid)

update

(p*2

,l,r,k);if

(r>mid)

update

(p*2+1

,l,r,k)

; t[p]

.sum=

(t[2

*p].sum+t[

2*p+1]

.sum)

%mod;

}int

query

(int p,

int l,

int r)

//標記深度 子樹大小 重兒子 父親

void

dfs1

(int x,

int f,

int deep)

}//每個點的新編號 賦值每個點的初始值到新編號上 處理每條重鏈

void

dfs2

(int x,

int topf)

}//每一條重鏈的新編號是連續的

//x->y之間的路徑

intqrange

(int x,

int y)

if(dep[x]

>dep[y]

)swap

(x,y)

; ans+

=query(1

,id[x]

,id[y]);

return ans%mod;

}int

qson

(int x)

void

uprange

(int x,

int y,

int k)

if(dep[x]

>dep[y]

)swap

(x,y)

;update(1

,id[x]

,id[y]

,k);

}void

upson

(int x,

int k)

intmain()

dfs1

(r,0,1

);dfs2

(r,r)

;build(1

,1,n);

for(

int i=

0;i)else

if(k==2)

else

if(k==3)

else

}return0;

}

P3384 模板 輕重鏈剖分(樹鏈剖分模板)

入口 題目描述 如題,已知一棵包含 nn 個結點的樹 連通且無環 每個節點上包含乙個數值,需要支援以下操作 操作 11 格式 1 x y z1 x y z 表示將樹從 xx 到 yy 結點最短路徑上所有節點的值都加上 zz。操作 22 格式 2 x y2 x y 表示求樹從 xx 到 yy 結點最短...

P3384 輕重鏈剖分(樹剖模板)

如題,已知一棵包含 nn 個結點的樹 連通且無環 每個節點上包含乙個數值,需要支援以下操作 操作 11 格式 1 x y z1xyz 表示將樹從 xx 到 yy 結點最短路徑上所有節點的值都加上 zz。操作 22 格式 2 x y2xy 表示求樹從 xx 到 yy 結點最短路徑上所有節點的值之和。操...

模板 輕重鏈剖分

目錄後記 模板 輕重鏈剖分 傳送門總的來說,就是乙個不難理解,碼量 的東西 推幾篇題解,講得不錯 線段樹 必備 倍增lca 可以幫助理解,不會應該也可以 鏈式前向星 存圖,不會有人不會吧 重兒子 子樹結點最多的兒子 重邊 某個點到它的重兒子連成的邊 重鏈 重邊連成的鏈 輕兒子 除重兒子外的其它兒子 ...