D - 道路の整備 / Road Maintenance Editorial by admin
claude4.8opus-highSummary
This is a problem of finding the minimum cost to make the absolute difference between adjacent section heights at most \(D\) by performing operations to increase (and not decrease) the height of each section. We can solve this by finding the “minimum height” each section must ultimately reach, and then summing the costs to raise them to those heights.
Analysis
Important Observation: There is a lower bound for each section indicating “it must be at least this height in the end.”
First, since heights cannot be decreased, the final height \(A_i'\) must satisfy \(A_i' \geq A_i\).
Furthermore, from the constraint that the difference between adjacent sections is at most \(D\), if a section \(j\) has a height of \(A_j\), then any section \(i\) at a distance of \(|i-j|\) from it must satisfy:
\[A_i' \geq A_j - D \cdot |i-j|\]
(since the height can decrease by at most \(D\) for each step to the side).
Since this must hold for all \(j\), the lower bound for the height of section \(i\) is:
\[h_i = \max_{1 \leq j \leq N} \bigl(A_j - D \cdot |i-j|\bigr)\]
(Since the term for \(j=i\) is \(A_i\), this naturally satisfies \(h_i \geq A_i\) as well).
This lower bound \(h_i\) itself is a feasible solution
In fact, if we set the final heights to exactly \(h_i\), the adjacent sections will satisfy \(|h_i - h_{i+1}| \leq D\) (since each term \(A_j - D|i-j|\) changes by at most \(D\) between adjacent indices, their maximum value behaves the same way).
In other words, \(h_i\) is the coordinate-wise minimum solution that simultaneously achieves the “minimum height satisfying all constraints” for each section. Since any feasible solution must satisfy \(A_i' \geq h_i\), and the cost \(C_i > 0\) is positive, setting the height of every section to exactly \(h_i\) yields the minimum cost.
Therefore, the answer is:
\[\sum_{i=1}^{N} C_i \cdot (h_i - A_i)\]
Problems with the Naive Approach
Calculating \(h_i\) by checking all \(j\) for each \(i\) according to the definition takes \(O(N^2)\) time, which is too slow for \(N \leq 10^6\). We need a more efficient way.
Algorithm
We can compute \(h_i = \max_j (A_j - D|i-j|)\) by splitting the absolute value into left and right parts, using two passes (forward and backward scans).
Contribution from the left (\(j \leq i\)): The maximum value of \(A_j - D(i-j)\) can be computed sequentially from left to right using the recurrence relation: $\(L_i = \max(A_i,\ L_{i-1} - D)\)\( This is because as we move one step to the right, all previous candidates decrease by \)D$.
Contribution from the right (\(j \geq i\)): Similarly, we can compute the contribution from the right: $\(R_i = \max(A_i,\ R_{i+1} - D)\)$ sequentially from right to left.
Finally, by setting \(h_i = \max(L_i, R_i)\), we can find the lower bound for all sections in \(O(N)\) time.
In the implementation, we can achieve this in two passes: first, we store \(L_i\) in h[i] during the forward scan, and then during the backward scan, we compute \(R_i\) and update h[i] to be the maximum of h[i] and \(R_i\).
Concrete Example: For \(A = [5, 0, 0, 3]\) and \(D = 2\):
- Forward scan: \(L = [5, 3, 1, 3]\)
- Backward scan: \(R = [5, 1, 3, 3]\)
- \(h = \max(L, R) = [5, 3, 3, 3]\)
For instance, for section 2, even if we decrease the height from section 1’s height of \(5\) by \(D=2\) as much as possible, it can only go down to \(3\), so \(h_2 = 3\). The cost to increase the heights is calculated as \(\sum C_i(h_i - A_i)\).
Complexity
- Time Complexity: \(O(N)\)
- Space Complexity: \(O(N)\)
Implementation Points
Since \(A_i, C_i\) and \(N\) can be large, the answer can exceed the range of a 32-bit integer. In Python, integers automatically have arbitrary precision, so it is not an issue, but in languages like C++, you must use
long long.Since \(N = 10^6\) is large, fast I/O using
sys.stdin.buffer.read()is recommended in Python to speed up the execution.By storing the forward scan values in
hand updating them in-place withmaxduring the backward scan, we can complete the calculation in two passes without allocating extra arrays.Source Code
import sys
def main():
data = sys.stdin.buffer.read().split()
idx = 0
N = int(data[idx]); idx += 1
D = int(data[idx]); idx += 1
A = [int(x) for x in data[idx:idx+N]]; idx += N
C = [int(x) for x in data[idx:idx+N]]; idx += N
# h_i = max_j (A_j - D*|i-j|) via forward and backward passes
h = A[:]
# forward pass
prev = A[0]
for i in range(1, N):
v = prev - D
ai = A[i]
cur = ai if ai > v else v
h[i] = cur
prev = cur
# backward pass, combine with h (take max)
prev = A[N-1]
# last element: forward value already A[N-1] effectively, but ensure
if A[N-1] > h[N-1]:
h[N-1] = A[N-1]
for i in range(N-2, -1, -1):
v = prev - D
ai = A[i]
b = ai if ai > v else v
prev = b
if b > h[i]:
h[i] = b
ans = 0
for i in range(N):
ans += C[i] * (h[i] - A[i])
sys.stdout.write(str(ans) + "\n")
main()
This editorial was generated by claude4.8opus-high.
posted:
last update: