1 条题解
-
0
题目重述 我们有一个数组,由 个“块”压缩表示:第 个块是 个连续的 。 保证相邻块的值不同:。
每一秒,同时删除所有满足以下条件的元素:
它是数组的第一个元素,或者
它不等于它左边的元素
删除后,剩余部分按原顺序拼接。
定义数组的“强度”为它变为空数组所需的秒数。
对于每个前缀 ,求该前缀所描述数组的强度。
核心观察
- 理解删除规则 规则等价于:每一秒,每个“连续相同值”的块中,只保留最左边的那个元素,其余都被删除。
例如,块 有 个 :
第 秒后:只剩第一个
第 秒后:第一个 还在(因为它是新的第一个),但块只剩它自己,所以这一秒它也会被删除? 让我们仔细模拟:
初始:
第 秒:删除 (因为 保留, 与 相等所以删除?不对!规则是 或 才删除。,,相等,所以 不满足删除条件!)
等等,我理解错了。让我重新解读规则:
所有 使得 或 会被删除。
这意味着:
第一个元素()一定被删除。
对于 ,如果 (即它是某个连续段的新开头),则它也被删除。
如果 (即它在连续段内部),则它不被删除。
所以实际上,每一秒,所有“连续段的最左边元素”都被删除,而连续段内部的元素保留。
例:
连续段:, , ,
最左边元素:第一个 ,第一个 ,第一个 ,第一个 → 这些被删除
剩下:(原来每个段去掉第一个后剩下的)
这与题目给的示例一致。
- 块的生命周期 对于一个长度为 的块( 个相同值):
每一秒,该块的长度减少 (因为最左边那个被删了)
所以仅考虑这个块自己,它需要 秒才能完全消失。
但块之间会相互影响。考虑相邻的两个块 (值 ,长度 )和 (值 ,长度 ),且 。
在 存在的每一秒, 的第一个元素都会被删除(因为 的第一个元素 它的左边元素,即 的最后一个元素,只要 还存在)。 所以只要 还在, 的长度每一秒也会减少 (因为它的第一个元素被删了,但 内部剩余元素仍然连续)。
更精确地说:
当 和 都存在时,每一秒: 长度减 , 长度减 。
当 先消失后, 成为新的最左块(或者前一个块是别的),但它的剩余长度需要继续减少。
这提示我们:一个块的“剩余时间”依赖于它左边块的生命周期。
算法思路 我们可以从左到右处理块,维护一个栈。栈中每个元素表示一个“活着的”块,记录它的剩余长度和它的值。
对于新块 :
如果栈顶的值等于 ,则合并:将 加到栈顶的长度上,然后弹出栈顶(因为合并后需要重新计算)。
否则,我们需要计算这个新块需要多少秒才能消失。设当前栈顶块的长度为 ,值为 。
只要栈非空且栈顶块的长度 ,则栈顶块会先于当前块消失。在此期间,当前块每一秒也减少 。 所以当栈顶块消失时,当前块已经消耗了 秒,剩余长度为 。
但更关键的是,当前块的“生存时间”必须至少为 (因为栈顶块消失后,当前块成为新的比较对象)。
实际上,我们需要维护的是:当前块需要的时间 = ,但这里栈顶时间指的是栈顶块完全消失所需的时间。
正确做法是维护每个块“完全消失所需的时间”。设 为第 个块(从左到右处理后的块)的消失时间。
当我们加入一个新块 时:
如果与栈顶值相同,合并: 增加,栈顶弹出,然后重新计算这个合并块的时间。
否则,新块的消失时间初始为 。然后看栈顶:
如果栈顶的消失时间 当前块的消失时间,则栈顶会在当前块之前或同时消失。但当前块会“等待”栈顶消失后才成为新的左端,所以当前块的消失时间至少为栈顶消失时间 。 因此,更新当前块消失时间为 ,然后弹出栈顶(因为栈顶已经被“覆盖”)。
重复直到栈空或栈顶消失时间 当前块消失时间。
然后将当前块 以消失时间压栈。
最后,整个前缀的答案就是栈底(第一个块)的消失时间。
时间复杂度 每个块最多入栈出栈一次,。
- 1
信息
- ID
- 6647
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 4
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者