1 条题解
-
0
题目解法:F. Farmer John's Favorite Function
一、核心数学观察
1.1 开方取整的等价性
由于我们只关心 ,可以证明每一步都取整不影响最终结果的整数部分:
$$f(i) = \lfloor \sqrt{f(i-1) + a_i} \rfloor \quad (i > 1) $$这样我们完全在整数域上操作,避免了浮点数精度问题。
1.2 前面元素的影响极其有限
关键结论:当 时,改变 最多只会让 变化 。
更一般地,对于任意连续的一段区间,前一个区间的结果只会让当前区间的结果要么不变,要么恰好增加 。这个性质是解题的基础。
二、分块策略
2.1 块大小的选择
将数组分成大小为 的块。如果 不是 的倍数,在数组前面补 使其成为 的倍数。
选择 的原因:经过 步递推后,前面值的影响被压缩到最多 ,这使得每个块的行为可以简化为两种可能。
2.2 块内信息提取
对于每个块 ,我们计算两个关键值:
:假设 时,计算得到的 的值
:最小的非负整数,使得当 时,
可以通过从块内从右往左逆向计算得到:
- 设目标值为
- 逆向递推公式:进入第 步前的值
- 最终得到的值即为阈值
含义:
- 如果 ,则
- 如果 ,则
如果逆向计算过程中值超过 ,说明无论前面多大都无法让结果达到 ,此时 视为无穷大。
三、块的合并规则
每个块用二元组 表示。合并两个相邻块 和 时,结果 分三种情况:
情况1:
- 左块输出最大为 ,仍然小于
- 右块输出始终为
- 合并后 ,(无法触发 )
情况2:
- 左块输出最小为 ,已经
- 右块输出始终为
- 合并后 ,
情况3:
- 左块输出为 或
- 当左块输出 (即输入 )时,右块输出
- 当左块输出 (即输入 )时,右块输出
- 合并后 ,
四、数据结构维护
4.1 线段树维护块序列
将每个块视为线段树的一个叶子节点,存储其 信息。内部节点存储左右子节点合并后的信息。
- 单点更新:修改数组元素后,重新计算所在块的 ,更新叶子节点并向上合并,复杂度
- 整体查询:查询根节点,得到整个数组的 ,由于初始 且通常 ,答案即为
4.2 复杂度分析
- 块大小 ,块数
- 每个块计算 需要 时间
- 线段树操作
- 每次更新:
- 总复杂度:
五、算法正确性说明
-
取整的正确性:递推中每一步取整不影响最终 ,因为开方和加法在取整意义下可以交换顺序。
-
块内二值性的正确性:由于 ,前面值的影响最多让结果增加 ,因此每个块的输出只有 或 两种可能。
-
合并规则的正确性:三种情况覆盖了 与 的所有大小关系,每种情况对应右块输出的确定值,同时正确传递了阈值信息。
-
线段树的正确性:块的合并满足结合律,因此线段树可以正确维护整个序列的复合函数。
六、解题关键总结
步骤 关键点 数学观察 开方取整可下放;前面值影响范围 分块 块大小 ,利用影响范围小的性质 块内处理 计算 : 是零输入输出, 是增加 的阈值 块间合并 三种情况合并两个 ,得到新的二元组 数据结构 线段树维护块序列,支持快速更新和查询 最终答案 查询整个序列,取 值
七、算法扩展
除了线段树,也可以使用根号分治(块大小设为 或常数如 ),复杂度 ,在 时也能通过。
- 1
信息
- ID
- 6255
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者