点分树和边分治
我能在只会点分治和三度化的情况下发明这两个算法吗?
点分树
当暴力需要使用点分治时考虑。
直接把点分治找出的分治中心按照分治树连接父子关系。
P6329 【模板】点分树 | 震波
考虑暴力是点分治:我们在点分的时候枚举分治中心,计算 \(u\to v\) 需要经过分治中心时 \(v\) 对 \(u\) 的贡献。
然后我们回到点分树的结构。当我们需要询问 \(x\) 时,我们向上枚举分治中心来重新模拟点分治。显然这只有 \(\mathcal O(\log n)\) 次枚举。
然后考虑得到分治中心之后我们怎么计算贡献。显然在这一层分治时需要计算贡献的点们位于这个点的子树内,但不能是 \(x\) 所在的那个儿子子树。
最后来考虑怎样的一个点能对答案做出贡献。假设我们枚举的分治中心是 \(rt\),那么我们需要查询在 \(rt\) 子树内,但不属于 \(x\) 所在儿子子树中的点 \(y\) 的权值和,满足原树上存在 \(dis(x,rt)+dis(rt,y)\le k\)。考虑我们可以直接搞定 \(dis(x,rt)\),于是我们想要知道有多少个点满足 \(dis(rt,y)\) 小于等于一个常数。
注意到我们在点分树上维护数据结构具有类似树套树的美好性质:任何一个点如果都存在于它的祖先的数据结构中,那么每个点实际上只在 \(\mathcal O(\log n)\) 个数据结构中。而且我们在点分树上还可以肆意地扫描它的子树。所以我们暴力对每个点扫描整个子树,把 \(dis(rt,y)\) 按照点分树上的 dfs 序插进动态开点权值线段树,修改的时候也只改变 \(\mathcal O(\log n)\) 棵线段树。
然后考虑抠掉那部分。我们再搞一个线段树,维护 \(dis(fa_{u},v)\),就能简单地抠掉了。
这题动态开点线段树有点卡空间,可以用动态开点树状数组写。

浙公网安备 33010602011771号