点分治 / 点分树题目集

学了这么久的点分治 / 点分树,感觉自己还是只会做点裸题……这都要国赛了感觉自己吃枣药丸。

CSAcademy Round 10 Yury's Tree

题意

给定一棵 \(n\) 个点的树,每条边有一个边权。接下来有 \(m\) 次操作分为以下两种:

  • 1 u 查询 \(u\) 号点的价值。
  • 2 x y z 表示对于 \(x\) 子树的所有点 \(u\) ,如果 \(u\)\(x\) 的路径上的边权全都大于等于 \(y\) ,就给 \(u\) 的价值加上 \(z\)

\(n,m \le 3 \times 10^5 , TL = 1.5s\) 。原题范围 \(n,m \le 10^5,TL = 4s\)

题解

原题的做法是个不太优美的根号算法,事实上这个题是存在 \(\log\) 级别做法的。

首先假设修改全部在询问之前。注意到这里你需要保证路径最大值大于等于某个数,因此可以考虑一下点分治。分治到当前分治重心的时候,把分治重心沿原树的父亲往上爬,直到遇到上一分治重心或根节点,把这条路径上的有效修改操作提取出来。某一次查询的点 \(u\) 如果可以被修改操作 \((x,y,z)\) 贡献到,那么 \(u\) 到分治重心的最大边权 \(w\) 就要小于等于 \(y\)。这可以很容易地统计出来。

我们再加上时间这一维,就只要拿一个树状数组维护就行了,复杂度 \(O(n \log^2 n)\)

总结

对于有根树上的一些问题,思路也不要被局限,点分治也是一个很好的角度;对于树上的某些单点查询,可以考虑修改对查询的贡献,而不是把整个值维护出来。

一个经典问题

题意

给出一棵 \(n\) 个点的有根树,每个结点上有一个一次多项式。求每个结点到根的多项式乘积的和。

\(n \le 10^5\)

题解

树上路径问题,可以继续考虑点分治。点分治之后,假如求出了当前分治重心到根节点的多项式乘积,那么接下来只需要对于每一个不包含根节点的子树,计算以这个子树的根节点为新的根,关于这个子树的一个子问题即可。最后加起来统一卷积。

考虑如何求出这条路径的多项式乘积,直接暴力分治 \(\text{FFT}\)\(O(n \log^2 n)\) 的,加上点分治就是 \(O(n \log^3 n)\) ,不太能过。注意到其实这个分治 \(\text{FFT}\) 有大量的重复计算,因此优化可以从这里下手。我们只需要不断地找到该路径上的下一个点分中心,就可以直接得到下一个点分中心到根的路径的乘积,这样可以得到 \(O(\log n)\) 个多项式,其中第 \(i\) 个多项式长度级别不会超过 \(\frac{n}{2^i}\)。显然把他们卷起来的时间复杂度是 \(O(n \log n)\),因此总复杂度降到了 \(O(n \log^2 n)\)

Codeforces 936E Iqea

题意

有一间房子由 \(n\) 个格子组成,第 \(i\) 个格子位于坐标 \((x_i,y_i)\) ,保证所有属于房子的格子是四连通的,同时保证所有不属于房子的格子也是四连通的。

房子里有好多的橘猫。橘猫想吃东西。接下来会发生 \(m\) 个事件,第 \(i\) 个事件可以用三个数 \(ty,x,y\) 表示。

  • \(ty = 1\) 则表示坐标 \((x,y)\) 处出现了一大碗猫粮,猫粮是吃不完的。

  • \(ty = 2\) 则表示坐标 \((x,y)\) 处出现了一只橘猫,他会走向距离最近的猫粮去吃,注意猫不能走出房子。保证坐标都在房子内。

对于每个 \(ty = 2\) 的事件,橘猫想让你告诉他们,距离最近的猫粮距离是多少。

\(n,m,x_i,y_i \le 3 \times 10^5\)

题解

由于属于房子和不属于房子的格子都是四联通的,因此联通部分不存在环。

如果把所有垂直方向上相邻的格子缩成一个点,那么这样就形成了一棵树。考虑一只橘猫和一碗猫粮在枚举了相遇的那个节点之后,应该怎么算距离。可以发现,一定是先找到对应的到这个节点的最短路径,然后在这个节点上走完剩下的路。这样的话,只要在每个分治重心存下这个分治区域中,所有的猫粮到该分治重心的最短距离,以及到了之后的位置,询问时就可以到每个分治中心去查询了。由于到每个分治重心处还需要 \(O(\log n)\) 的代价维护,因此时间复杂度 \(O(n \log^2 n)\)

总结

模型转化是这道题的一大核心;对于树上动态维护一个点到一个点集的最短路,可以考虑用点分树来维护;可以把分治重心当做类似中转站的处理点。

Luogu P5311

题意

给定一棵 \(n\) 个点的树,每个节点有一个颜色。\(q\) 询问从 \(x\) 出发,只经过编号在 \([l,r]\) 中的点,所能到达的点的颜色种数。

\(n,q \le 10^5\)

题解

建出点分树,一个很重要的性质是,对于询问 \((l,r,x)\)\(x\) 所在的一个连通块,必定完全包含在点分树上某一个节点 \(p\) 的子树里,满足 \(p \in [l,r]\)。证明可以考虑,如果不存在这样的 \(p\) ,那么这个联通块必然会被某个分治重心分开成若干个联通块。

接下来我们只要沿着点分树向上爬,就不难找到这个 \(p\) 。对于当前分治重心,求出每个点到这个分治重心的路径编号最大最小值,问题就可以化为,给定若干个区间,每个区间有一种颜色,每次询问会给定一个区间 \([l,r]\) ,求被 \([l,r]\) 完整包含的区间颜色种数。不难发现只需要离线树状数组扫一遍就行了,复杂度 \(O(n \log^ 2 n)\)

总结

题目的难点主要在前面的性质发现。思路可能要有意识地往这上面靠。

posted @ 2019-07-04 20:17  ShichengXiao  阅读(1133)  评论(0编辑  收藏  举报