1 条题解
-
0
题解
思路
状态转移
扫描到程序的某个位置时,设 表示:在之前从未把 赋为 的前提下,当前 的最小删除花费。不可达状态的值为正无穷。初始只有 。
对于
set y v,删除它会使所有可达状态的花费增加 ;保留它则会把所有原状态汇聚到 ,花费是转移前的全局最小值。因此,若 ,可先对所有状态加 ,再用原全局最小值更新 。若 ,这条指令必须删除,只执行全局加法。处理条件块
进入
if y时,只有当前值为 的状态会执行块内指令,其余状态直接跳到块后。因此可以从当前状态集中取出 ,把外层集合的 位置改为正无穷,并用只包含状态 的新集合执行块内指令。遇到对应的
end时,将外层集合与块内集合按值逐点取最小值。这恰好合并了“跳过块”和“执行块”两类路径。用栈保存每层外层状态集,即可迭代处理任意深度的嵌套,避免系统递归栈溢出。
做法
子任务一
当 时,枚举所有
set指令的删除子集。对每个子集按语义模拟程序,检查是否曾把 赋为 ,并对合法方案取最小花费。设
set行数为 ,时间复杂度为 ,空间复杂度为 。子任务二
值域不超过 时,直接用数组保存所有 。每条
set线性扫描数组完成全局最小值、全局加法和单点更新;条件块结束时线性合并两个数组。设值域大小为 ,时间复杂度为 ,空间复杂度为 ,其中 为最大嵌套深度。
满分做法
用动态开点线段树保存有限的 。每个结点保存区间最小值和区间加法懒标记,从而在 时间对整棵树加上花费,并在 时间查询或更新单个值。
条件块结束时,对两棵动态线段树做破坏式合并:若其中一棵在某区间没有结点,直接返回另一棵;否则下传标记,递归合并子区间并取最小值。每个动态结点在合并过程中只会被处理常数次。
最终所有可达终态中的最小花费就是根结点的最小值。
复杂度
每条指令最多创建 个结点。满分做法的总时间复杂度为 ,总空间复杂度为 。
- 1
信息
- ID
- 1260
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者