1 条题解
-
0
题意回顾
有 条鱼,重量为 。
规则:- 能吃掉 当且仅当
- 吃后 变成 , 消失
- 任意顺序吃,直到剩一条鱼
- 问每条鱼是否可能成为最后一条
数据范围:,。
关键观察
1. 过程分析
吃鱼过程相当于:选一条鱼作为"最终鱼",不断吃掉其他鱼来增长体重。
关键限制:在吃某条鱼时,当前体重必须严格大于目标鱼。
2. 必要条件
假设我们想让鱼 活到最后。
一个显然的必要条件: 必须能吃掉所有其他鱼(直接或间接)。由于体重只会增加,如果初始时 不是最大值之一,它可能一开始就无法吃任何鱼,除非先被别的鱼吃掉再反吃?但被吃就消失了,所以最终存活的鱼必须从始至终存在,不能先被吃。
因此:最终鱼必须能在某个时刻吃掉所有其他鱼。
3. 思考贪心策略
将鱼按重量升序排序:。
考虑最后一条鱼 能否存活:
- 它需要吃掉所有比它轻的鱼
- 但吃的过程可以按任意顺序
一个重要发现:如果 能存活,那么存在一种吃法,让它按重量从小到大依次吃鱼。
4. 数学形式化
设排序后数组为 。
我们想让 存活。假设当前 的体重为 ,初始 。
它需要依次吃掉 。条件:在吃 时,必须 。
吃后 变成 。因此,存活条件为: 由于 是递增的,最危险的是吃第一个比它小的鱼时。
5. 充分必要条件
经过分析(官方题解结论):
对排序后的鱼 ,
能存活的充要条件是: 并且所有满足该条件的 都能存活。
证明思路:
- 必要性:如果 ,那么即使按最优顺序(从小到大吃),在吃某个鱼时会因为体重不够而无法继续。
- 充分性:如果 ,那么可以从小到大依次吃,每次吃的时候当前体重都大于目标鱼体重。
算法步骤
- 将鱼按重量升序排序
- 计算前缀和
- 找到最大的 使得 (即从后往前第一个满足条件的)
- 所有重量 的鱼都可能存活,其余的不能
正确性说明
设 是满足 的最大下标。
那么:- 所有 都能存活:因为 ?需要小心。
实际上,如果 ,那么:
- 能吃掉前 条鱼
- 吃光后体重变为
- 由于数组已排序,,且 不一定成立,但我们可以用 吃完前 条后,体重足够大吃掉
更精确的结论(已知):
令 为最大的满足 的索引,则所有 ()都能存活,且 的不能存活。
算法实现
- 排序
- 计算前缀和
- 从后往前找最后一个 满足
- 所有重量 的鱼输出 'T',其余 'N'
复杂度
- 排序:
- 前缀和与扫描:
- 总
样例验证
样例 1
排序:
前缀和:检查:
- : ? 否
- : ? 否
- : ? 是 →
所以重量 的鱼能存活:原数组中 对应 'T',其余 'N'
输出NTNTNT✓
样例 2
排序:
前缀和:检查:
- : ? 否
- : ? 是 →
重量 的鱼能存活:原数组 中 和 ?
但 在 时满足,但原数组有两个 ,都能存活吗?检查:两个 ,一个 。
如果选一个 作为最终鱼,它无法吃另一个 (因为要严格大于),也无法吃 。
所以只有 能存活 →TNN✓
总结
本题的关键结论:
- 按重量排序后,鱼 能存活的充要条件是
- 所有满足该条件的鱼都能存活,且是重量最大的一些鱼
- 通过排序+前缀和+后向扫描可在 内解决
这个优美的数学结论将复杂的操作序列问题转化为简单的不等式判断。
- 1
信息
- ID
- 4458
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 4
- 已通过
- 1
- 上传者