|
| 1 | +# [Problem 2528: Maximize the Minimum Powered City](https://leetcode.com/problems/maximize-the-minimum-powered-city/description/?envType=daily-question) |
| 2 | + |
| 3 | +## Initial thoughts (stream-of-consciousness) |
| 4 | +We need to maximize the minimum "power" across all cities after adding up to k stations. Each station contributes to a contiguous window of length 2*r+1 around its position. The problem smells like a binary-search-on-answer: for a candidate minimum power X, check if we can, with ≤ k added stations, make every city's power at least X. |
| 5 | + |
| 6 | +To check feasibility for X we need to know each city's current power from existing stations (a sliding window sum). Then we must decide where to place additional stations greedily so each city meets X. A common greedy: sweep left-to-right, keep track of extra contribution from stations we already placed (use a difference array to expire contributions), and when the current city is under X, place enough stations at the rightmost position that still covers this city (i + r, capped by n-1). Placing them as far right as possible maximizes their future effect. Update the diff/ending index so recorded extra contributions expire appropriately. |
| 7 | + |
| 8 | +So plan: |
| 9 | +- Compute base power for each city via prefix sums (sliding window). |
| 10 | +- Binary search answer in [0, sum(stations) + k]. |
| 11 | +- For each mid, simulate greedy check with diff array in O(n). |
| 12 | + |
| 13 | +Careful with indices for "expiry" of added station contributions: if we place at pos = min(n-1, i + r), a station there covers cities from pos - r to pos + r. When pos = i + r (the common case), the coverage on the sweep starting at i is from i to i + 2r, so expiry index is i + 2r + 1. Cap by n. |
| 14 | + |
| 15 | +## Refining the problem, round 2 thoughts |
| 16 | +Edge cases: |
| 17 | +- r = 0: each station affects only its own city; check reduces to raising individual values. |
| 18 | +- Very large k (up to 1e9) — must use 64-bit arithmetic for counts. |
| 19 | +- n up to 1e5, station values up to 1e5 => sum(stations) up to 1e10; sums and high bounds must be stored in Python ints (fine). |
| 20 | +- Binary search upper bound: sum(stations) + k is safe (no city can get more than all stations). |
| 21 | +- Time: O(n log(sumS + k)) which is fine (~1e5 * ~40). |
| 22 | + |
| 23 | +Implementation details: |
| 24 | +- Compute base array using prefix sums: base[i] = prefix[min(n-1, i+r)] - prefix[max(0, i-r)-1] |
| 25 | +- In feasibility check: |
| 26 | + - Use diff array of length n (all zeros). |
| 27 | + - running_added = 0 |
| 28 | + - For each i: running_added += diff[i]; curr = base[i] + running_added |
| 29 | + - If curr < mid: need = mid - curr; if need > remaining_k -> fail; else remaining_k -= need; running_added += need; end = min(n-1, i + 2*r); if end + 1 < n: diff[end+1] -= need |
| 30 | +- Return True if loop completes. |
| 31 | + |
| 32 | +Complexities: |
| 33 | +- Precompute base: O(n) |
| 34 | +- Each check: O(n) |
| 35 | +- Binary search iterations: O(log(sumS + k)) up to ~40 |
| 36 | +- Total: O(n log(sumS + k)) time, O(n) extra space. |
| 37 | + |
| 38 | +## Attempted solution(s) |
| 39 | +```python |
| 40 | +from typing import List |
| 41 | + |
| 42 | +class Solution: |
| 43 | + def maxPower(self, stations: List[int], r: int, k: int) -> int: |
| 44 | + n = len(stations) |
| 45 | + # prefix sums |
| 46 | + prefix = [0] * n |
| 47 | + prefix[0] = stations[0] |
| 48 | + for i in range(1, n): |
| 49 | + prefix[i] = prefix[i-1] + stations[i] |
| 50 | + # compute base power for each city: sum of stations in [i-r, i+r] |
| 51 | + base = [0] * n |
| 52 | + for i in range(n): |
| 53 | + left = max(0, i - r) |
| 54 | + right = min(n - 1, i + r) |
| 55 | + base[i] = prefix[right] - (prefix[left - 1] if left > 0 else 0) |
| 56 | + |
| 57 | + total_existing = prefix[-1] |
| 58 | + lo, hi = 0, total_existing + k # inclusive upper bound |
| 59 | + |
| 60 | + def can_achieve(target: int) -> bool: |
| 61 | + # difference array to manage added station contributions |
| 62 | + diff = [0] * (n + 1) # one extra for easier expiry handling |
| 63 | + running_added = 0 |
| 64 | + remaining = k |
| 65 | + for i in range(n): |
| 66 | + running_added += diff[i] |
| 67 | + curr = base[i] + running_added |
| 68 | + if curr < target: |
| 69 | + need = target - curr |
| 70 | + if need > remaining: |
| 71 | + return False |
| 72 | + remaining -= need |
| 73 | + running_added += need |
| 74 | + # place these 'need' stations at position pos = min(n-1, i + r) |
| 75 | + # their coverage ends at end = min(n-1, pos + r) |
| 76 | + # For pos = min(n-1, i + r), this end is min(n-1, i + 2*r) |
| 77 | + end = min(n - 1, i + 2 * r) |
| 78 | + # subtract from diff at end+1 to expire their effect |
| 79 | + if end + 1 < len(diff): |
| 80 | + diff[end + 1] -= need |
| 81 | + # continue |
| 82 | + return True |
| 83 | + |
| 84 | + ans = 0 |
| 85 | + while lo <= hi: |
| 86 | + mid = (lo + hi) // 2 |
| 87 | + if can_achieve(mid): |
| 88 | + ans = mid |
| 89 | + lo = mid + 1 |
| 90 | + else: |
| 91 | + hi = mid - 1 |
| 92 | + return ans |
| 93 | +``` |
| 94 | +- Notes: |
| 95 | + - We compute base city powers using prefix sums in O(n). |
| 96 | + - The binary search tries candidate minimum powers; each feasibility check simulates greedy placements using a difference array to amortize added contributions. Each check is O(n). |
| 97 | + - Time complexity: O(n log(sum(stations) + k)). Space complexity: O(n) for base and diff arrays. |
| 98 | + - The greedy choice (placing needed stations at the rightmost position that still covers the current city) maximizes future benefit and is correct when sweeping left-to-right. |
0 commit comments