1 条题解
-
0
题意理解
我们有 个天线,第 个天线高度为 ,它只能向距离在 内的天线发送信息。 如果天线 和 可以互相通信(即 且 ),则它们的通信成本为 。
给定 个询问 ,问区间内所有天线对中,能互相通信的最大成本是多少,若没有则输出 。
第一步:直接暴力思路
最直接的方法是枚举所有 ,检查它们是否能互相通信,然后计算 ,取最大值。 检查条件为:
且
且
即:
对于询问 ,只考虑 。
复杂度: 对每对天线,再乘 会超时。
第二步:固定一个天线,考虑它能和谁通信
对于天线 ,它能发送信息的天线 必须满足:
并且 能接收 的信号需要满足:
所以 能互相通信的条件是:
$$\begin{cases} i + A_i \le j \le i + B_i \\ j - B_j \le i \le j - A_j \end{cases} $$第三步:转化为二维数点问题
我们可以把问题看作:每个天线 对应一个“事件”,询问区间 内所有满足互相通信条件的天线对 的最大 。
这类区间最值问题常用扫描线 + 线段树/树状数组解决。
关键观察
对于一对 ,。 因此我们可以分别考虑两种情况:
,则成本
,则成本
所以问题变成:对于所有合法 ,求 。
第四步:离线处理 我们可以对询问按右端点排序,从左到右扫描 ,维护之前所有 的信息。
对于固定的 ,哪些 能与之互相通信?
条件:
$$\big( i \in [j - B_j, j - A_j] \big) \ \land\ \big( j \in [i + A_i, i + B_i] \big) $$第一个条件给出了 的范围,第二个条件是对 的限制,可以看作 在插入时带有生效区间 。
第五步:扫描线 + 线段树维护 我们按 从小到大扫描:
当 进入 的生效区间 时,将 加入数据结构。
当 离开 的生效区间()时,将 移除。
对于每个 ,我们查询区间 内的所有 ,计算 (当 )或 (当 )的最大值。
具体实现方法
我们需要维护两种信息:
对于 ,求 最大 → 即求区间内 的最小值。
对于 ,求 最大 → 即求区间内 的最大值。
因此我们可以用两棵线段树:
一棵维护区间 最大值
一棵维护区间 最小值
当扫描到 时:
在 区间内,用 更新答案(如果 存在且 )
用 更新答案(如果 存在且 )
第六步:处理互相通信条件 注意:我们上面只考虑了 对 的范围限制 ,而 对 的限制 是通过扫描线加入/移除 来保证的。
这样我们确实覆盖了互相通信的两个条件。
第七步:算法流程
离线所有询问,按 排序。
准备两个线段树:seg_max 和 seg_min,初始值设为 和 。
准备事件:
对于每个 ,在 时将 插入数据结构
在 时将 移除
按 扫描:
处理所有在 时刻加入的 ,更新线段树位置 为
处理所有在 时刻移除的 ,更新线段树位置 为无效值
对于所有 的询问 :
在区间 内(如果区间有效)查询 minH 和 maxH
用 和 更新该询问的答案
输出每个询问的最终答案(若未更新则输出 )
第八步:复杂度
每个 加入/移除一次: 次操作
每个询问查询一次: 次操作
线段树操作
总复杂度 ,可过。
公式总结
互相通信条件:
成本:
扫描线维护:
加入事件: 时加入
移除事件: 时移除
查询区间:
这样我们就得到了一个高效的 解法。
- 1
信息
- ID
- 4304
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者