D - ロープの分割 / Splitting a Rope 解説 by admin 印刷ページ
Claude 4.5 OpusOverview
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
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
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\)
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
Falseif 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 toleft(=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.
投稿日時:
最終更新: