zoukankan      html  css  js  c++  java
  • 点分治 / 点分树题目集

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

    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 imes 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)

    题解

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

    考虑如何求出这条路径的多项式乘积,直接暴力分治 ( ext{FFT})(O(n log^2 n)) 的,加上点分治就是 (O(n log^3 n)) ,不太能过。注意到其实这个分治 ( ext{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 imes 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))

    总结

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

  • 相关阅读:
    C#读写xml文件
    实现SQL_SERVER的双机实时备份
    Microsoft .NET Pet Shop 4 架构与技术分析
    xp系统运行asp.net时候出现“服务器应用程序不可用”的必杀
    获取服务器根域名
    C#如何创建Xml文件
    用C#创建XML[简单代码]
    关闭Viewstate
    数字签名
    IE插件
  • 原文地址:https://www.cnblogs.com/ShichengXiao/p/11134674.html
Copyright © 2011-2022 走看看