1 条题解
-
0
问题理解
我们有 枚导弹,每枚导弹有高度 和速度 。
拦截规则:系统第一发可以拦截任意导弹,之后拦截的导弹必须满足 高度不高于前一发 且 速度不大于前一发。
目标:在 拦截数量最多 的前提下,计算 每枚导弹被拦截的概率。
关键观察
1. 问题转化
这实际上是一个 二维最长不升子序列(2D LIS) 问题:
- 我们需要找一个序列 ,满足:
2. 图论视角
将导弹看作节点,如果导弹 能在导弹 之后被拦截(即 且 ),则从 向 连一条有向边。
这样形成一个 DAG(有向无环图),原问题转化为:- 求 DAG 上的 最长路径(即最多拦截数量)
- 计算每个节点在 所有最长路径 中出现的概率
算法框架
第一步:求最长链长度
定义:
- :以第 枚导弹结尾的最长链长度
- :以第 枚导弹结尾的、长度为 的链的方案数
转移: 对于每个 ,找到所有满足 且 的 :
- 如果 ,则更新 和
- 如果 ,则累加
优化:
由于直接枚举是 ,需要数据结构优化。对导弹按 降序排序( 相同时按 降序),然后用 树状数组/线段树 维护 信息:- 在树状数组中查询 的区域中的最大 及对应方案数
- 然后将当前导弹的 插入树状数组
第二步:计算概率
定义:
- :以第 枚导弹开头的方案数(反向DP)
- :以第 枚导弹结尾的方案数(即 )
关键公式:
导弹 被拦截的概率 =
[ \frac{\sum_{\text{所有最长链经过i}} 1}{\text{最长链总方案数}} = \frac{f[i] \times g[i]}{\text{总方案数}} ] 其中:- 可以通过 反向DP 求得(按 升序、 升序排序,用树状数组维护)
- 就是第一步中求得的
- 总方案数 =
实现细节
1. 离散化
由于 ,需要先对 和 分别离散化,将值域映射到 。
2. 排序技巧
- 正向DP:按 降序, 相同时按 降序(确保能转移到当前导弹的都在前面处理过)
- 反向DP:按 升序, 相同时按 升序
3. 数据结构维护
树状数组/线段树需要维护:
- 最大值
- 对应方案数
- 合并时:如果 ,取 和 ;如果相等,累加
4. 概率计算
对于每枚导弹 :
- 如果 ,说明不在任何最长链上,概率为
- 否则,概率 =
样例分析
样例:
4 3 30 4 40 6 60 3 30最长链长度为 ,最长链有 条:
- (2,4):导弹2→导弹4
- (3,4):导弹3→导弹4
- (1,4):导弹1→导弹4
因此:
- 导弹1、2、3分别出现在 的最长链中
- 导弹4出现在所有最长链中,概率为
输出:
2 0.33333 0.33333 0.33333 1.00000
复杂度分析
- 离散化:
- 两次DP(正向+反向):
- 总复杂度:,可处理
总结
这道题的核心是:
- 二维最长不升子序列 的求解与优化
- DAG上最长路径计数 的正反两次DP
- 概率计算 通过方案数相乘除以总方案数
- 数据结构优化 处理二维偏序关系
通过离散化+树状数组/线段树,将 优化到 ,是处理大规模二维偏序问题的典型方法。
- 我们需要找一个序列 ,满足:
- 1
信息
- ID
- 3757
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 5
- 已通过
- 1
- 上传者