公式

D - ロープの分割 / Splitting a Rope 解説 by admin 印刷ページ

Claude 4.5 Opus

Overview

This problem asks us to divide a rope consisting of \(N\) segments into \(K\) pieces while minimizing the length of the longest piece. “Minimizing the maximum value” is a classic binary search problem.

Analysis

Focus on the Problem’s Properties

This problem has the format “minimize the maximum value.” For such problems, binary search on the answer is effective.

Issues with the Naive Approach

If we try to exhaustively search all \(K-1\) cutting positions, we need to choose \(K-1\) positions from \(N-1\) possible locations, giving us \(\binom{N-1}{K-1}\) combinations. When \(N\) or \(K\) is large, this results in TLE.

Change of Perspective

Consider the decision problem: “Can we divide the rope such that the maximum length is at most \(X\)?”

  • If \(X\) is too large → Easy to divide (likely Yes)
  • If \(X\) is too small → Cannot divide (No)

We use binary search to find the minimum \(X\) for which this decision problem returns Yes.

Decision Method (Greedy Algorithm)

“Can we divide into at most \(K\) pieces with maximum length at most \(X\)?” can be determined in \(O(N)\) using a greedy approach.

Example: For \(A = [3, 5, 4, 7, 6, 2]\), \(K = 3\), \(X = 12\): 1. Process segments from left to right 2. If adding to the current rope doesn’t exceed \(X\), add it 3. If it would exceed, cut there and start a new rope

\([3, 5, 4]\) → Total is 12 ≤ 12, so OK
Adding \([7]\) gives 12 + 7 = 19 > 12, so cut
\([7, 6]\) → Total is 13 > 12, so cut (but 7 must be included alone)
…and so on for the decision.

Algorithm

  1. Set the Binary Search Range

    • Lower bound \(\text{left} = \max(A)\): No matter what, we need at least the length of the largest segment
    • Upper bound \(\text{right} = \sum A\): The length when keeping everything as one piece
  2. Execute Binary Search

    • Calculate \(\text{mid} = (\text{left} + \text{right}) / 2\)
    • Check if we can divide into at most \(K\) pieces with maximum length \(\text{mid}\)
      • If possible → Answer is at most \(\text{mid}\), set \(\text{right} = \text{mid}\)
      • If not possible → Answer is greater than \(\text{mid}\), set \(\text{left} = \text{mid} + 1\)
  3. Decision Function (Greedy Algorithm)

    • Process segments from left to right, adding to the current rope
    • If it exceeds \(X\), cut there and increment the count by 1
    • If the final count is at most \(K\), division is possible

Complexity

  • Time Complexity: \(O(N \log S)\)
    • \(S = \sum A_i\) (maximum \(10^{14}\))
    • Binary search runs \(O(\log S)\) times, each decision takes \(O(N)\)
  • Space Complexity: \(O(N)\)
    • Only storing array \(A\)

Implementation Notes

  • In the decision function, immediately return False if any single segment is greater than \(X\)
  • In the greedy approach, if adding to the current sum would exceed the limit, “cut there”
  • The binary search termination condition is left < right, and the answer converges to left (= right)
  • In Python, there’s no need to worry about integer overflow, so large values are safe

Source Code

def can_divide(A, K, max_len):
    """Check if we can divide into at most K pieces with maximum length max_len"""
    count = 1
    current_sum = 0
    
    for a in A:
        if a > max_len:
            return False
        if current_sum + a > max_len:
            count += 1
            current_sum = a
        else:
            current_sum += a
    
    return count <= K

def solve():
    N, K = map(int, input().split())
    A = list(map(int, input().split()))
    
    # Binary search
    # Minimum: length of the largest segment (cannot be smaller than this)
    # Maximum: sum of all segments (case of keeping as one piece)
    left = max(A)
    right = sum(A)
    
    while left < right:
        mid = (left + right) // 2
        if can_divide(A, K, mid):
            right = mid
        else:
            left = mid + 1
    
    print(left)

solve()

This editorial was generated by claude4.5opus.

投稿日時:
最終更新: