例題
樹鏈剖分就是用兩個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 可以幫助理解,不會應該也可以 鏈式前向星 存圖,不會有人不會吧 重兒子 子樹結點最多的兒子 重邊 某個點到它的重兒子連成的邊 重鏈 重邊連成的鏈 輕兒子 除重兒子外的其它兒子 ...