「CodeForces-191C」Fools and Roads
LCA+树上差分/树链剖分,求树边的染色次数
题意
给定一个$N$节点的树,以及树上的$k$条简单路径(端点用$u$,$v$表示),求树上的各条边被$k$条简单路径经过的总次数。
解法
LCA+树上差分
对于树上的简单路径$path(u,v)$,如果对于每一次查询,都对路径$path(u_i,v_i)$上经过的每一条边的权值+1,时间复杂度为$O(k*n)=1e10$,显然我们需要优化时间复杂度。
我们引入树上差分(树的前缀和)来优化查询。
树上差分
对于树,有如下两个性质:
- 任意两个节点之间有且只有一条路径;
- 根节点确定时,一个节点只有一个父亲节点。
由此,在自根节点向下进行DFS时,对于$path(u,v)$的其中任意一点$u’≠r$,若$u’$被访问,则$u’$的父亲节点一定被访问。
基于这样的性质,我们将树上的路径$path(u,v)$分割为两条链,有$r=LCA(u,v)$,路径$path(u,v)$覆盖的边为$u→r$,$r→v$,对两条链分别进行差分。
关于边的差分中,$r=LCA(u,v)$不包含在内。因此考虑链$u→r$,有cf[u]++
,cf[r]--
;同样的,对于链$r→v$,有cf[v]++
,cf[r]--
,即
1 | for each(u,v) |
在完成所有$path$的查询后,自根节点进行$DFS$求树上每个点的前缀和,此时,对于树边$path(u,v)$,$cf[v]$即为此条边经过的总次数,即,对于树上的每条边$path(u,v)$,有
$$ans[path(u,v)]=cf[v]$$
时间复杂度为$O(n)$
如,对于样例1
对每一组查询$path$求LCA后有
DFS求前缀和,即为所求解
代码
1 |
|
树链剖分
(待补)