公式

C - 中継局の設置 / Installation of Relay Stations 解説 by admin

Claude 4.6 Opus (Thinking)

Overview

This problem asks you to select 2 or more locations from candidate sites on a road to install relay stations, such that the distance between any two adjacent relay stations is at most \(D\), while minimizing the total construction cost.

Analysis

Key Insight: The Optimal Solution Always Consists of a Pair of 2 Points

First, let’s sort the candidate sites by coordinate.

Core observation: In the optimal solution, it is always sufficient to select exactly 2 locations.

This is because, if there exists a valid solution selecting \(k \geq 2\) locations, then any two coordinate-adjacent points among them have distance at most \(D\). Selecting only that adjacent pair still forms a valid solution, and its cost is at most the original solution’s cost (since the costs of the other points are positive).

In other words, this problem can be rephrased as:

Among all pairs \((i, j)\) whose coordinate difference is at most \(D\), find the minimum value of \(C_i + C_j\).

Naive Approach

Checking all pairs takes \(O(N^2)\), which results in TLE for \(N = 2 \times 10^5\).

Optimization

If we sort by coordinate, then for each point \(i\), the set of points “\(j < i\) satisfying \(X_i - X_j \leq D\)” forms a contiguous interval. We need to efficiently find the minimum \(C_j\) within this interval, which can be done in \(O(N)\) using a sliding window minimum (monotonic queue).

Algorithm

  1. Sort the candidate sites in ascending order of coordinates.
  2. While maintaining a left pointer, for each point \(i\), do the following:
    • Add point \(i-1\) to the window (update the monotonic queue).
    • Remove points from the left end of the window where \(X_i - X_j > D\).
    • If the queue is not empty, compute \(dp_i = C_i + C_{\text{queue front}}\) (= minimum cost within the window).
  3. The minimum value of \(dp_i\) across all \(i\) is the answer. If no valid pair exists, output -1.

Concrete Example

For \(N=3, D=5\), with points \((0, 100), (5, 1), (10, 100)\):

  • \(i=1\) (coordinate 5): Window contains the point at coordinate 0. \(5-0=5 \leq 5\) → \(dp = 1 + 100 = 101\)
  • \(i=2\) (coordinate 10): Window contains points at coordinates 0 and 5. \(10-0=10 > 5\), so remove the point at coordinate 0. \(dp = 100 + 1 = 101\)

Answer: \(101\)

Complexity

  • Time complexity: \(O(N \log N)\) (dominated by sorting; the sliding window is \(O(N)\))
  • Space complexity: \(O(N)\)

Implementation Notes

  • Monotonic queue (deque): Store indices in the queue, and remove elements from the back as long as C[dq[-1]] >= C[i-1] before adding, so that the front always holds the point with the minimum cost within the window.

  • Window management: The window for point \(i\) consists of points “to the left of \(i\) and within distance \(D\)”. Note that point \(i\) itself is not included in the window; it is added when processing the next point.

  • -1 determination: If no adjacent pair has distance at most \(D\), no valid solution exists, so output -1.

    Source Code

import sys
from collections import deque

def main():
    input_data = sys.stdin.buffer.read().split()
    idx = 0
    N = int(input_data[idx]); idx += 1
    D = int(input_data[idx]); idx += 1
    
    points = []
    for i in range(N):
        x = int(input_data[idx]); idx += 1
        c = int(input_data[idx]); idx += 1
        points.append((x, c))
    
    # Sort by coordinate
    points.sort()
    
    if N < 2:
        print(-1)
        return
    
    # dp[i] = minimum cost of a valid selection where point i is the LAST (rightmost) relay station
    # We need at least 2 stations selected.
    # 
    # For each point i, we can either:
    # 1. Start a new chain: point i is paired with some point j < i where X[i] - X[j] <= D
    #    cost = C[i] + C[j]  -> we want min C[j] for j in valid range
    # 2. Extend an existing chain: dp[i] = C[i] + min(dp[j]) for j where X[i] - X[j] <= D
    #
    # Actually, let's define:
    # dp[i] = minimum total cost of a valid selection (>=2 stations) where station i is the rightmost
    #
    # dp[i] = C[i] + min over j in window { min(dp[j], C[j]) }
    # where window = { j : j < i and X[i] - X[j] <= D }
    #
    # Because if we pick j as the previous station:
    # - If j already has a chain ending at it (dp[j] is valid), cost contribution from left part is dp[j]
    # - If j is the start of a new pair with i, cost contribution is C[j]
    # - So we want min(dp[j], C[j]) over valid j
    #
    # dp[j] >= C[j] always (since dp[j] includes C[j] plus at least one more station's cost)
    # So min(dp[j], C[j]) = C[j] always!
    #
    # Wait, that's not right. dp[j] = cost of chain ending at j with >=2 stations, which includes C[j].
    # So dp[j] >= C[j] + (cost of at least one other station) > C[j].
    # Therefore min(dp[j], C[j]) = C[j].
    #
    # So dp[i] = C[i] + min(C[j]) for j in window where X[i] - X[j] <= D and j < i.
    # And dp[i] is valid (represents a chain of >=2) whenever such j exists.
    #
    # Wait, but this would mean we always just pick pairs? No - because the chain constraint requires
    # ALL consecutive selected stations to be within D. If we select {a, b, c} with a < b < c,
    # we need b-a <= D AND c-b <= D. So it's not just about pairs.
    #
    # The issue: if we select a subset S, ALL consecutive gaps must be <= D.
    # So if we pick the pair (j, i) that's fine - cost C[j] + C[i].
    # If dp[j] represents a valid chain ending at j, and X[i] - X[j] <= D, then we can extend it.
    # Cost = dp[j] + C[i].
    #
    # We want the minimum over all valid chains. The answer is min(dp[i]) for all i.
    #
    # dp[i] = C[i] + min over j in window { min(dp[j], C[j]) }
    # Since dp[j] >= 2*min_cost > C[j] is NOT necessarily true if C[j] is large...
    # Actually dp[j] includes C[j] + at least one more C value, so dp[j] > C[j] if costs are positive.
    # Since C[j] >= 1, dp[j] >= C[j] + 1 > C[j]. So indeed min(dp[j], C[j]) = C[j].
    #
    # Therefore dp[i] = C[i] + min{C[j] : j < i, X[i] - X[j] <= D}
    # Answer = min(dp[i]) over all valid i, or -1.
    
    INF = float('inf')
    
    X = [p[0] for p in points]
    C = [p[1] for p in points]
    
    # Sliding window minimum of C[j] for j in window [left, i-1] where X[i] - X[j] <= D
    ans = INF
    # Use a deque for sliding window minimum of C values
    dq = deque()  # stores indices, C[dq[0]] is the minimum in window
    left = 0
    
    for i in range(N):
        # Add point i-1 to the window (if i > 0)
        if i > 0:
            while dq and C[dq[-1]] >= C[i-1]:
                dq.pop()
            dq.append(i-1)
        
        # Remove points out of window from front
        while dq and X[i] - X[dq[0]] > D:
            dq.popleft()
        
        if dq:
            dp_i = C[i] + C[dq[0]]
            if dp_i < ans:
                ans = dp_i
    
    print(ans if ans < INF else -1)

main()

This editorial was generated by claude4.6opus-thinking.

投稿日時:
最終更新: