cpp
//解决"最大化最小供电量" 问题 核心思路是二分查找 + 贪心策略 + 差分数组
//目标是让所有城市的供电量中最小的那个值尽可能大。
class Solution {
public:
long long maxPower(vector<int>& stations, int r, int k) {
//计算初始供电量(差分数组 cnt)
int n = stations.size();
vector<long long> cnt(n + 1);// 差分数组,大小n+1避免越界
for (int i = 0; i < n; i++) {
int left = max(0, i - r);// 第i座城市的供电站覆盖的左边界
int right = min(n, i + r + 1);// 覆盖的右边界(差分数组的右边界是开区间)
cnt[left] += stations[i];// 左边界加供电站数量
cnt[right] -= stations[i];// 右边界减供电站数量
}
//check 函数(验证目标值是否可达)
auto check = [&](long long val) -> bool {
vector<long long> diff = cnt;// 复制差分数组(避免修改原数组)
long long sum = 0;// 当前城市的实际供电量(前缀和)
long long remaining = k;// 剩余可建造的电站数量
for (int i = 0; i < n; i++) {
sum += diff[i];
if (sum < val) {// 若当前供电量不足,需要补建电站
long long add = val - sum;//需要补建的数量
if (remaining < add) {// 剩余电站不够,目标不可达
return false;
}
remaining -= add;// 消耗剩余电站
// 补建的电站应放在尽可能靠右的位置(覆盖范围最大)
int end = min(n, i + 2 * r + 1);// 补建电站的覆盖右边界
diff[end] -= add;// 差分数组标记:从i到end-1增加add
sum += add;// 当前城市的供电量更新为val
}
}
return true;// 所有城市都满足≥val,目标可达
};
//二分查找框架
long long lo = ranges::min(stations);// 下界:初始最小供电站数量(保守估计)
long long hi = accumulate(stations.begin(), stations.end(), 0LL) + k;// 上界:总电站+额外k座
long long res = 0;
while (lo <= hi) {
long long mid = lo + (hi - lo) / 2;// 中间值(当前猜测的最小供电量)
if (check(mid)) {// 若能实现所有城市供电量≥mid
res = mid;// 更新答案
lo = mid + 1;// 尝试更大的目标
} else {
hi = mid - 1;// 目标太大,尝试更小的
}
}
return res;
}
};