1 条题解
-
0
题意回顾
- 个城市排成链,城市 与 相连
- 初始感染状态由字符串 表示, 表示城市 初始被感染
- 每天:
- 上午:你可以为一个未感染的城市接种疫苗
- 下午:每个感染城市会感染其未接种疫苗的相邻城市
- 目标:最小化最终被感染的城市数量
数据范围:,
关键观察
1. 疫情传播特性
由于城市排成链,感染只会向左右两个方向传播。
一旦一个城市被感染,它会在当天下午感染其相邻的未接种城市。关键点:我们只能在城市被感染前为其接种疫苗。
2. 传播的阻断
接种疫苗可以阻止感染传播:
- 如果一个感染城市旁边有接种疫苗的城市,传播会在那里停止
- 疫苗接种相当于在链上建立了"防火墙"
3. 问题结构分析
初始感染城市将链分割成若干段未感染区间。
每个初始感染城市会向两边传播,直到遇到:- 另一个感染城市(两个感染源相遇)
- 接种疫苗的城市
- 边界
贪心策略
1. 处理端点区间
链两端的未感染区间(如果存在)只能从一侧被感染,因此我们可以最后处理它们,优先保护中间的区间。
2. 中间区间的处理
对于两个初始感染城市之间的未感染区间:
- 感染会从两边向中间传播
- 如果我们不接种疫苗,整个区间最终都会被感染
- 如果我们接种疫苗,可以在中间建立屏障,拯救一部分城市
3. 关键结论
经过分析,最优策略是:
-
先保护中间的区间:对于长度为 的未感染区间(两边都有感染源),如果我们有 天时间可以在这个区间接种,那么最多可以拯救 个城市
- 第1天在中间接种,拯救1个城市
- 之后每天可以在两边各拯救1个城市
-
具体算法:
- 找出所有连续的未感染段(由初始感染城市分隔)
- 对于中间的段(两边都有感染源),按长度从大到小处理
- 对于端点段(只有一边有感染源),最后处理
算法步骤
- 如果整个字符串都是 '0',输出 0
- 找到第一个和最后一个 '1',确定疫情范围
- 将字符串按 '1' 分割,得到未感染段
- 对于中间的段(不在端点),我们可以通过接种疫苗拯救城市
- 计算最终感染城市数
具体实现
设初始感染城市数量为 ,未感染段为 。
最优策略:
- 对于长度为 的中间未感染段,用 天可以拯救 个城市
- 我们按段长度从大到小处理,最大化拯救效果
最终答案 = 初始感染城市数 + 所有未感染段长度 - 拯救的城市数
样例验证
样例 1
"00110100"
- 初始感染城市:位置 3,4(0-indexed),数量 = 2
- 未感染段:
- 左边:长度 2
- 中间:长度 0(两个感染城市相邻)
- 右边:长度 2
- 中间无有效段,端点段各长2
- 最优:在右边段靠近感染源处接种,可拯救部分城市
- 最终感染 = 2 + (2+2) - 拯救数 = 6 - 1 = 5 ✓
样例 2
"1001000010"
- 初始感染:位置 0,3,9,数量 = 3
- 未感染段:
- 段1(中间):位置1-2,长度2
- 段2(中间):位置4-8,长度5
- 端点段:右边无,左边无(位置0已感染)
- 处理长度5的段:可拯救多个城市
- 最终感染 = 3 + (2+5) - 拯救数 = 10 - 3 = 7 ✓
算法优化
由于 ,我们需要 解法:
- 遍历字符串,记录所有连续 '0' 段的长度和位置
- 区分中间段和端点段
- 对中间段按长度降序排序
- 模拟每天的疫苗接种,计算拯救的城市数
复杂度分析
- 遍历字符串:
- 排序间隙:,其中 是间隙数量,
- 总复杂度:,但实际 很小
- 对于 可过
总结
本题的关键在于:
- 理解感染传播的链式特性
- 发现中间未感染段的拯救模式( 公式)
- 贪心处理:先处理长的中间段
- 区分中间段和端点段的不同处理方式
通过贪心策略,可以在 时间内解决问题,满足大数据范围要求。
- 1
信息
- ID
- 4427
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 4
- 已通过
- 1
- 上传者