1 条题解
-
0
D. Boss, Thirsty 详细题解
1. 问题重述与转化
我们有一个 的网格,第 行第 列的值为 。
- 第 天必须选择 至少一个连续段(子数组)(),当天利润为:
- 相邻两天必须满足:
- 至少有一个公共类型($\{l_i, \dots, r_i\} \cap \{l_{i-1}, \dots, r_{i-1}\} \neq \emptyset$)
- 至少有一个新类型($\{l_i, \dots, r_i\} \not\subseteq \{l_{i-1}, \dots, r_{i-1}\}$)
目标:最大化 。
2. 关键转化:用“边”代替“格子”
考虑一行 个格子,有 条边,编号 。
格子 ()位于边 与边 之间。选择格子区间 ()等价于选择两条不同的边:
使得区间包含边 到边 之间的所有格子。
为了简便,我们直接定义:
- 左端点 (0-based 边编号,范围 )
- 右端点 (范围 )
那么区间为 表示格子 到 。
利润:
定义前缀和:
$$\text{pref}[0] = 0,\quad \text{pref}[k] = \sum_{j=1}^k A_{i,j} $$那么利润为:
其中 。
3. 相邻天的约束转化
第 天选择了 ()。
第 天选择 ()。条件:
-
至少一个公共格子
区间 与 有交集
且
这等价于 且 。 -
至少一个新格子
区间 不是 的子集
要么 (左端新),要么 (右端新)。
合并两个条件,可以证明等价于:
$$\text{至少满足以下一条:} \quad L < L' < R \quad \text{或} \quad L < R' < R $$也就是说,新区间必须严格包含上一区间的至少一个端点(左端点 或右端点 )。
4. 动态规划状态设计
因为只需要知道上一个区间的端点之一,可以设计两种 DP:
- :处理完前 行,且第 行选择的区间左端点为 的最大总利润。
- :处理完前 行,且第 行选择的区间右端点为 的最大总利润。
其中 ,。
5. 转移方程
假设我们已经知道第 行的 和 ,现在要计算第 行的 。
第 行选择区间 ,利润:
$$\text{profit} = \text{pref}_i[R] - \text{pref}_i[L] $$上一行区间的端点(左或右)记为 ,要求 。
如果上一行是以 作为左端点,则上一行利润为 ;
如果是以 作为右端点,则上一行利润为 。
我们取最大值:于是:
$$dpR[i][R] = \max_{0 \le L < p < R} \left[ -\text{pref}_i[L] + bestPrev[p] + \text{pref}_i[R] \right] $$$$dpL[i][L] = \max_{L < p < R \le m} \left[ -\text{pref}_i[L] + bestPrev[p] + \text{pref}_i[R] \right] $$
6. 高效计算(前缀/后缀最大值优化)
6.1 计算
固定 ,我们要最大化:
其中 。
这可以分两步:
-
先对所有 ,计算:
$$val[p] = bestPrev[p] + \max_{0 \le L < p} (-\text{pref}_i[L]) $$其中 是前缀最大值(从 到 )。
-
再对 ,取:
$$dpR[i][R] = \text{pref}_i[R] + \max_{0 \le p < R} val[p] $$这里 也是前缀最大值。
所以可以在 内求出所有 。
6.2 计算
对称地,固定 :
$$dpL[i][L] = -\text{pref}_i[L] + \max_{L < p < R \le m} \left[ bestPrev[p] + \text{pref}_i[R] \right] $$先对每个 计算:
$$val2[p] = bestPrev[p] + \max_{R > p} \text{pref}_i[R] $$其中 是后缀最大值。
然后:
$$dpL[i][L] = -\text{pref}_i[L] + \max_{p > L} val2[p] $$这也是后缀最大值。
7. 算法步骤总结
- 对每一行 预处理前缀和 。
- 初始化第一行:
- 对所有 ,$dpL[1][L] = dpR[1][R] = \text{pref}_1[R] - \text{pref}_1[L]$(直接取区间 )。
- 但第一行没有前一行约束,所以 应取所有 的最大利润:$$dpL[1][L] = \max_{R>L} (\text{pref}_1[R] - \text{pref}_1[L]) $$同理 $dpR[1][R] = \max_{L<R} (\text{pref}_1[R] - \text{pref}_1[L])$。 这也可以前缀/后缀最大值 求。
- 对 到 :
- 计算 。
- 用前缀最大值求所有 。
- 用后缀最大值求所有 。
- 答案为 。
8. 时间复杂度
- 每行 ,共 行 → 。
- 所有测试用例的 ,完全可行。
- 1
信息
- ID
- 6311
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 2
- 标签
- 递交数
- 4
- 已通过
- 1
- 上传者