1 条题解
-
0
题目分析
我们有一棵 个节点的树,每个节点有一个初始高度 ()。支持两种操作:
- 洒水操作:以节点 为中心,半径 内的所有节点高度乘以 后对 取模
- 查询操作:询问某个节点的当前高度
关键限制:,这个限制是解题的突破口。
核心思路
1. 问题转化
直接遍历每个操作影响的所有节点是不可行的( 太大)。由于 很小,我们可以考虑标记传递的方法。
核心思想:将一次洒水操作的影响记录在相关节点上,查询时再收集所有影响。
2. 标记设计
对于每个节点 ,我们维护一个数组 (),表示"对距离节点 为 的所有节点施加的乘法因子的累积乘积"。
为什么数组大小是 ?
- 因为一个洒水操作 可能影响 的祖先节点,对于祖先节点 ,它到 的距离为 ,那么它需要记录对距离自己为 的节点的影响。
- 最坏情况下 ,此时 ; 时 ;同时还要考虑另一个方向的影响。
3. 洒水操作的处理
对于洒水操作 :
- 从 开始向上遍历祖先(包括 自己),设当前节点为 , 到 的距离为
- 如果 ,停止向上遍历
- 剩余半径
- 将 乘以 (模 )
这样,我们就把洒水操作的影响记录在了 及其祖先节点上。
4. 查询操作的处理
要查询节点 的当前高度:
- 从 开始向上遍历祖先(包括 自己),设当前节点为 , 到 的距离为
- 如果 ,停止向上遍历
- 用 乘到结果上(模 )
为什么这样是正确的?
- 对于任意洒水操作 ,如果它影响了节点 ,那么 到 的距离
- 在洒水时,我们在 的某个祖先 处记录了影响,且
- 查询时, 会访问到 ,且 正好对应洒水时记录的位置
5. 时间复杂度分析
- 每次洒水操作:向上遍历至多 个节点,
- 每次查询操作:向上遍历至多 个节点,
- 总时间复杂度:,在 时非常高效
算法优势
- 利用了小半径特性: 使得我们可以为每个节点存储大小为 的数组
- 标记永久化:不需要下推标记,简化了实现
- 树上差分思想:将区间修改转化为多个点的标记更新
- 离线处理:算法本质是在线算法,但思想类似于离线差分
总结
这道题的解决关键在于:
- 发现 很小的特殊性质
- 设计合适的标记结构
- 利用树的父子关系实现高效的标记更新和收集
- 通过"洒水时分散标记,查询时收集标记"的方式避免直接遍历影响区域
这种"小半径操作 + 标记永久化"的思路在树上操作问题中非常有用,特别是当操作半径有上限时。
- 1
信息
- ID
- 4080
- 时间
- 4000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- 递交数
- 6
- 已通过
- 1
- 上传者