简介
点分治一般是用来处理树上路径问题
一般的思想是对于每条路径 $u\rightarrow v$,我们在 $lca(u,v)$ 处统计它们的贡献
对于一棵树,我们选择它的重心为根,然后统计每个点到根的权值和
这样就得到了所有以根为 $lca$ 的贡献
对于每个子树内的点对的贡献,我们递归进行处理
时间复杂度为 $O(log*\alpha)$,其中 $\alpha$ 为每层处理的时间复杂度
1 | bool vis[maxn]; |
例题
简要题意:给定一棵 $n$ 个点的无根树,每个点有一个物品,物品有重量 $w$,价值 $c$ 和数量 $d$ 这三个属性,现在要在树上做多重背包,给定重量 $m$,你现在可以选择的物品必须满足在一个连通块内,即如果你选了 $u$ 和 $v$ 中至少一个物品,那么 $u$ 和 $v$ 路径上的每个点你都必须至少选一次
$n\le 500,m\le 4000,w\le m,d\le 100$
简要题解:我们注意到合并两个背包的复杂度为 $O(m^2)$,而插入一个物品的复杂度为 $O(m)$,我们考虑求必须包含根节点的答案,然后按照点分的过程,求不包含当前根节点的答案
我们以 $dfs$ 序的逆序来背包,因为一个点的子树的 $dfs$ 序是一个段区间,我们当前考虑点 $i$,那么我们有两种抉择,不选 $i$,那么 $i$ 的子树也无法选择,那么 $f_i$ 就等于 $f_{i+sz_i}$;强制选择 $i$ 的一个物品,那么 $i$ 的子树可以随便选,那么 $f_i$ 就等于 $f_{i+1}$ 插入 $(w_i,c_i,d_i)$ 这个物品,注意需要保证这个物品至少选 $1$ 个,容易发现这两种情况合并只需要对应位置取 $max$ 即可
时间复杂度 $O(nm\log n)$,如果使用二进制拆分优化多重背包,那么时间复杂度为 $O(nm\log n\log d)$
树上依赖性背包