P7710 [Ynoi2077] stdmxeypz 题解

@LHF dalao 的题解进行一些补充说明。因为他讲的实在是太难懂了。最后在 @_•́へ•́╬_ dalao 的帮助下才勉强知道怎么做。不过他的代码非常简洁易懂,有需求的可以去看他的代码。我就不放了。

本文章分析复杂度时认为 nm 同阶。


首先需要明确的是,a 子树中所有与 a 的距离模 x 等于 y 的节点就是 a 子树中深度模 x 等于 (depa+y)modx(下文设其为 k)的节点。这样我们就可以把修改转化为将一个点的子树内所有深度模 xk 的节点权值加上 z

显然这种数据结构题不可能一个点一个点地去修改。因此先求出 dfn 序。这样就可以把修改变为对 [dfna,dfna+sizea1] 范围内(下文设其为 [l,r])的点进行一次区间操作。

但是我们不可能将 [l,r] 范围内的所有值统一加上某数。因此考虑建立一个以 dfn 序为 x 轴,深度为 y 轴的平面直角坐标系。把第 i 个点放在坐标 (dfni,depi) 上。这样我们就把修改转化为将所有横坐标在 [l,r] 范围内,纵坐标模 x=k 的节点权值全部加上 z

考虑直接暴力跳纵坐标,将跳到的水平线的 [l,r] 部分全部加上 z。因为 dfn 序与深度不对应的坐标是空着的,没有放点。所以把 [l,r] 的整个部分全部加上 z 不会影响正确性。

用某种数据结构维护每个纵坐标对应的水平线。当 x>n 时,暴跳的复杂度就是 O(n)×O(Modify) 的。查询时直接单点查询,因此复杂度是 O(1)×O(Query) 的。其中 O(Modify) 表示这种数据结构修改的复杂度,O(Query) 表示它查询的复杂度。因此使用修改 O(1),查询 O(n) 的序列分块+差分即可达到最优总复杂度。

xn 时,暴跳的时间复杂度可能会直接退化到 O(n)。因此考虑根号分治,将这部分特殊处理。开一个 n×n 的某种数据结构的数组,记为 DSi,j。每次修改对 DSx,k 执行一次让 [l,r] 区间加 z 的操作。询问时给答案加上 i=1nDS(i,depamodi,dfna) 即可。修改复杂度为 O(1)×O(Modify),询问复杂度为 O(n)×O(Query)。因此使用修改 O(n),查询 O(1) 的序列分块即可达到最优总复杂度。

因为这两种处理都用到分块,所以可以直接把散块暴力算,整块再分类讨论。

时空复杂度 O(nn)。时间限制十分充裕,但空间限制不够。可以通过调块长和根号分治的阈值卡过去。

代码就不放了,有需求的可以去看 @LHF dalao 的题解中的代码。

posted @   MeteorFlower  阅读(56)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示