公式

B - パイプの接続 / Connecting Pipes 解説 by admin

Gemini 3.0 Flash (Thinking)

Overview

This is a problem where you select \(M\) pipes (\(1 \le M \le N\)) from \(N\) pipes, connect them together, and find the maximum possible length, then determine whether that value is at least the target value \(D\). You need to account for deterioration when pipes are rusted, as well as the length reduction from joints when connecting pipes.

Analysis

1. Determine the “effective length” of each pipe

First, calculate the “actual usable length (effective length)” of each pipe individually. - If not rusted (\(B_i = 0\)): \(A_i\) - If rusted (\(B_i = 1\)): \(\max(A_i - C, 0)\)

This effective length is constant regardless of how other pipes are chosen.

2. Optimal combination when selecting \(M\) pipes

When selecting and connecting \(M\) pipes, the length of the finished product is expressed by the following formula: $\((\text{sum of effective lengths of the selected } M \text{ pipes}) - (M - 1) \times K\)$

To maximize this value, it is optimal to select the \(M\) pipes with the longest effective lengths. Therefore, if you sort all pipes in descending order of effective length beforehand, taking the top \(M\) pipes is the best strategy.

3. Determining the number of pipes \(M\) to select

Consider adding one more pipe to go from \(M\) pipes to \(M+1\) pipes. Let \(L_{M+1}\) be the effective length of the newly added pipe. The change in total length is as follows: - The new pipe’s length \(L_{M+1}\) is added - One more connection point is added, so the length decreases by \(K\)

In other words, the change is \(L_{M+1} - K\). If this value is positive, increasing the number of pipes makes the finished product longer. Conversely, if it is negative, increasing the number makes it shorter.

In this problem, we need to find the maximum value as the number of pipes \(M\) varies from \(1\) to \(N\). So after sorting the effective lengths, we can sequentially add them up and update the maximum value at each step to obtain the answer.

Algorithm

  1. Calculate effective lengths: For each pipe, compute the effective length \(L_i\) based on whether it is rusted or not, and store them in a list.
  2. Sort: Sort the list \(L\) in descending (largest first) order.
  3. Search for the maximum:
    • Start with the length \(L_0\) when selecting \(1\) pipe (\(M=1\)) as the tentative maximum.
    • Then, examine the remaining pipes in order from \(i = 1\) to \(N-1\), adding \((L_i - K)\) to the current length.
    • Maintain the maximum length across all steps.
  4. Decision: If the maximum is at least \(D\), output that value; otherwise, output \(-1\).

Complexity

  • Time complexity: \(O(N \log N)\)
    • Computing effective lengths takes \(O(N)\), sorting takes \(O(N \log N)\), and scanning for the maximum takes \(O(N)\). The overall bottleneck is the sorting step.
  • Space complexity: \(O(N)\)
    • \(O(N)\) memory is used for the list storing the effective lengths of the pipes.

Implementation Notes

  • Fast input: Since \(N\) can be as large as \(10^5\), in Python you can reduce execution time by reading all input at once using sys.stdin.read().split() or similar methods.
  • Negative values from rust: The rusted pipe length \(A_i - C\) can become negative, so make sure to always take max(0, A_i - C).
  • Initialization of the maximum: When \(M=1\), there are \(0\) connection points, so setting the initial value to \(L_0\) and processing the increment \((L_i - K)\) for the 2nd pipe onward in the loop makes the implementation simple.
# Outline of the process
current_sum = L[0] # Length of the first pipe
max_val = current_sum
for i in range(1, N):
    current_sum += (L[i] - K) # From the 2nd pipe onward, each additional pipe changes the total by L[i]-K
    if current_sum > max_val:
        max_val = current_sum

Source Code

import sys

def solve():
    # sys.stdin.read().split() を使用して、入力を一括で読み込みトークンに分割します。
    # これは Python において大量の入力を高速に処理する一般的な手法です。
    input_data = sys.stdin.read().split()
    if not input_data:
        return
    
    # 最初の 4 つのトークンは N, D, K, C です。
    N = int(input_data[0])
    D = int(input_data[1])
    K = int(input_data[2])
    C = int(input_data[3])
    
    # 各パイプの有効長(effective length)を計算します。
    # B_i = 0 の場合はそのまま A_i、B_i = 1 の場合は max(A_i - C, 0) となります。
    L = [0] * N
    for i in range(N):
        A = int(input_data[4 + 2*i])
        B = int(input_data[5 + 2*i])
        if B == 0:
            L[i] = A
        else:
            # 錆びているパイプの有効長は max(A - C, 0)
            effective = A - C
            if effective < 0:
                effective = 0
            L[i] = effective
    
    # 完成品の長さを最大化するために、有効長が長い順にパイプをソートします。
    # M 本のパイプを選んだとき、どの M 本を選ぶのが最適かは、有効長の大きい順に選ぶことと同義です。
    L.sort(reverse=True)
    
    # 完成品の長さの最大値を求めます。選ぶ本数 M は 1 以上 N 以下です。
    # M = 1 のとき、長さは選んだパイプの有効長そのものです。
    current_sum = L[0]
    max_val = current_sum
    
    # M = 2 から N までの場合を順番に試します。
    # M 本選んだときの長さは (M 本の有効長の合計) - (M - 1) * K です。
    # これは M-1 本の時の長さに (新しく選んだパイプの有効長 - K) を足すことで計算できます。
    for i in range(1, N):
        # i は 0-indexed なので、L[i] は (i+1) 本目に長いパイプの有効長です。
        current_sum += (L[i] - K)
        if current_sum > max_val:
            max_val = current_sum
            
    # 最大値が目標値 D 以上であればその値を出力し、そうでなければ -1 を出力します。
    if max_val >= D:
        print(max_val)
    else:
        print("-1")

if __name__ == "__main__":
    solve()

This editorial was generated by gemini-3-flash-thinking.

投稿日時:
最終更新: