题解:B4242 [海淀区小学组 2025] 蜂窝网络
前言
夜深人静灯未熄, 键盘声声敲梦稀。 代码如诗行行密, bug似雾层层迷。
逻辑清晰心自定, 算法精妙意无羁。 千行万行终成器, 运行成功笑满衣。
屏幕微光映眼底, 程序世界任我驰。 不问窗外风雨急, 只因心中有晨曦。
题目理解
我们有 n 个城市和 m 个信号发射塔,它们都分布在一条直线上。每个信号发射塔可以覆盖其左右距离不超过 r 的城市。我们的任务是找到最小的 r,使得所有城市都被至少一个信号发射塔覆盖。
初步思路
-
问题分析:
- 城市和信号发射塔的位置是给定的。
- 我们需要找到一个最小的
r,使得每个城市都在至少一个信号发射塔的覆盖范围内。
-
关键点:
- 对于每个城市,找到离它最近的信号发射塔。
- 所有城市到最近信号发射塔的最大距离就是我们需要的最小
r。
算法选择
为了高效地找到每个城市到最近信号发射塔的距离,我们可以使用二分查找。具体来说:
- 排序:将城市和信号发射塔的位置分别排序。
- 二分查找:对于每个城市,使用二分查找在信号发射塔的位置中找到离它最近的信号发射塔。
- 计算距离:计算每个城市到最近信号发射塔的距离,并取最大值作为
r。
具体实现
- 排序:将城市和信号发射塔的位置分别排序。
- 二分查找:对于每个城市,使用二分查找在信号发射塔的位置中找到离它最近的信号发射塔。
- 计算距离:计算每个城市到最近信号发射塔的距离,并取最大值作为
r。
代码实现
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
vector<int> a(n), b(m);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
for (int i = 0; i < m; ++i) {
cin >> b[i];
}
// 排序
sort(a.begin(), a.end());
sort(b.begin(), b.end());
int maxDist = 0;
for (int i = 0; i < n; ++i) {
// 使用二分查找找到离 a[i] 最近的信号发射塔
auto it = lower_bound(b.begin(), b.end(), a[i]);
int dist = INT_MAX;
if (it != b.end()) {
dist = abs(a[i] - *it);
}
if (it != b.begin()) {
dist = min(dist, abs(a[i] - *(it - 1)));
}
maxDist = max(maxDist, dist);
}
cout << maxDist << "\n";
return 0;
}
代码解释
-
输入处理:
- 读取城市数量
n和信号发射塔数量m。 - 读取城市位置
a和信号发射塔位置b。
- 读取城市数量
-
排序:
- 将城市位置
a和信号发射塔位置b分别排序。
- 将城市位置
-
二分查找:
- 对于每个城市
a[i],使用lower_bound在b中找到离它最近的信号发射塔。 - 计算该城市到最近信号发射塔的距离,并更新最大距离
maxDist。
- 对于每个城市
-
输出结果:
- 输出
maxDist,即最小的r。
- 输出
复杂度分析
-
时间复杂度:
- 排序的时间复杂度为
O(n log n + m log m)。 - 对于每个城市,使用二分查找的时间复杂度为
O(log m)。 - 总时间复杂度为
O(n log n + m log m + n log m)。
- 排序的时间复杂度为
-
空间复杂度:
- 使用两个向量存储城市和信号发射塔的位置,空间复杂度为
O(n + m)。
- 使用两个向量存储城市和信号发射塔的位置,空间复杂度为
总结
通过排序和二分查找,我们成功解决了这个问题。这道题目考察了二分查找的应用能力,同时也提醒我们在实际生活中要合理规划资源,最大化收益!希望这篇题解能帮助你更好地理解题目!