树上差分
顾名思义也就是在树上做差分,一般用于区间修改操作,通过只改变区间头和区间尾来实现对整个区间值的修改。
树上差分又分为点差分和边差分。
来个例题
[USACO15DEC] Max Flow P
题目简意:
给定一棵有
N
N
N 个点的树,所有节点的权值初始时都为
0
0
0。
有
K
K
K 次操作,每次指定两个点
s
,
t
s,t
s,t,将
s
s
s 到
t
t
t 路径上所有点的权值都
+
1
+1
+1。
请输出K次操作完毕后权值最大的那个点的权值。
2
≤
N
≤
5
×
1
0
4
,
1
≤
K
≤
1
0
5
2≤N≤5\times10^4,1≤K≤10^5
2≤N≤5×104,1≤K≤105。
点差分
我们设数组
d
d
d 表示每个节点减去它的子节点的值(有几个子节点就减几个)。
假如我们要把
u
u
u 到
v
v
v 路径上的所有点的点权都加
x
x
x,则我们可以把
d
u
+
x
,
d
v
+
x
,
d
l
a
c
−
x
,
d
f
a
(
l
c
a
)
−
x
d_u+x,d_v+x,d_{lac}-x,d_{fa(lca)}-x
du+x,dv+x,dlac−x,dfa(lca)−x 即可。
如图(用鼠标画的,有点丑):
边差分
边差分和点差分本质区别其实就是一个是边权和一个是点权。
我们可以把边附在点上,转化成“点差分”。
即将每个点连向自己父亲的边的边权差分,同样我们可以设一个
d
d
d 数组来记录差分。
为什么不是父亲连向儿子的边呢?是因为一个儿子只有一个父亲,但父亲可以有多个儿子。
假如我们要把
u
u
u 到
v
v
v 路径上的所有边的边权都加
x
x
x,则我们可以把
d
u
+
x
,
d
v
+
x
,
d
l
c
a
−
2
∗
x
d_u+x,d_v+x,d_{lca}-2*x
du+x,dv+x,dlca−2∗x 即可。
如图(这是我手画的哦):
由此可见,树上差分和 LCA 紧密相连。
(有点小简单)