#lydlx05x0E02. 干草堆
干草堆
题目描述
奶牛们讨厌黑暗。
为了调整牛棚顶的电灯的亮度,Bessie 必须建一座干草堆使得她能够爬上去够到灯泡。
一共有 大包的干草(从 到 编号)依靠传送带连续的传输进牛棚来。
第 包干草有一个宽度 。
所有的干草包的厚度和高度都为 。
Bessie 必须利用所有 包干草来建立起干草堆。
她可以想放多少包就放多少包来建立起草堆的地基(当然是紧紧的放在一行中)。
接下来她可以将下一个草包放在之前一级的上方来建立新的一级。
注意:每一级不能比下面的一级宽。
她持续的这么放置,直到所有的草包都被安置完成。
她必须按照草包进入牛棚的顺序堆放草包。
说得更清楚一些:一旦她将一个草包放在第二级 ,那么她不能将接下来的草包放在第一级上。
Bessie 的目标是建立起最高的草包堆。
输入格式
第 1 行:一个整数 。
第 2..N+1 行:第 行包含整数 。
输出格式
输出一个整数,表示草包堆的最高的高度。
样例
3
1
2
3
2
样例解释
干草包顺序
宽度依次为:, ,
可能的堆法
必须按照顺序 使用所有干草包。
尝试 1:
第一级:放 1 和 2(宽度和为 3),第二级:放 3(宽度为 3)。
但第二级宽度(3)等于第一级宽度(3),违反了“每一级不能比下面的一级宽”的规则(应该是严格小于吗?题目说“不能比下面的一级宽”,即宽度应 ≤ 下面一级,但通常理解为不能更宽,即 ≤ 下面一级。但样例中宽度相等似乎不允许)。
检查样例:第一级宽度 3,第二级宽度 3,相等,那么高度为 2。这似乎是允许的?但题目描述中说“不能比下面的一级宽”,相等是允许的。
尝试 2:
第一级:放 1(宽度 1),第二级:放 2(宽度 2),但 2 > 1,违反了“不能比下面的一级宽”。
所以不行。
尝试 3:
第一级:放 1 和 2 和 3(宽度和 6),只有一级,高度为 1。
高度较低。
尝试 4:
第一级:放 1 和 2(宽度和 3),第二级:放 3(宽度 3)。
高度为 2,且第二级宽度等于第一级宽度,不违反规则(因为“不能比下面的一级宽”意味着可以等于)。
因此最高高度为 2。
数据范围
问题分析
这是一个动态规划问题。
题意再梳理
- 给定一个序列 。
- 要将序列划分成若干连续段(每段对应一层),从底层到顶层依次对应序列的前缀到后缀。
- 要求:从上往下看(即从序列的后面往前面),每一层的总宽度不大于下一层的总宽度。
- 目标:最大化层数(高度)。
换句话说,我们需要将序列从后往前划分成若干段,使得段和的序列非严格递增(从顶到底)。
动态规划思路
设 表示将后缀 划分成若干层,且**第一层(即最顶层)**的宽度最小是多少,同时在这种情况下能获得的最大高度。
或者更直接地: 设 表示从 到 能堆的最大高度, 表示在这种情况下,最顶层(即第一层)的最小可能宽度。
转移时,我们考虑下一层(即更下面一层)从 开始(),那么当前层就是 ,宽度和为 (其中 是前缀和)。
要求:
- (当前层宽度不大于下一层宽度)
- 在满足条件 1 的 中,选择能使高度最大的,即 。
- 如果有多个 能使高度相同,则选择使当前层宽度 最小的,作为 。
优化
直接转移是 ,会超时。
可以观察到,最优的 是满足 且 尽量小的位置。因为 随 增大而增大, 随 变化有某种单调性。
更高效的解法是: 从后往前维护一个决策队列,队列中的元素 满足 单调递增(因为从后往前,越靠后的位置,其顶层宽度应该越小才能让前面的层放上去)。
对于当前 ,我们需要找到最小的 使得 。由于 ,移项得 。
因此我们可以维护一个关于 的单调队列,每次取队首满足条件的 作为转移点。
这样可以在 时间内解决。
实现提示
- 计算前缀和 。
- 从 到 倒序计算。
- 初始:, (虚拟位置)。
- 用单调队列维护可能的 ,满足 单调递减(这样队首的 最大,更容易满足 )。
- 对于每个 ,从队首弹出不满足条件的元素(即 ),最后一个被弹出的元素就是最优的 (因为队列按 递增, 递减,最后一个满足条件的 就是最小的 使得 )。
- 更新 和 ,然后将 加入队列。
最终答案
输出 。