C - 最短の登山ルート / Shortest Mountain Climbing Route Editorial by admin
Qwen3-Coder-480BOverview
Given a route consisting of consecutive points, find the minimum number of points such that the total elevation difference (sum of absolute differences between adjacent points) is at least \(K\).
Analysis
In this problem, the “total elevation difference” for the interval from point \(l\) to point \(r\) is defined as:
\[ \sum_{i=l}^{r-1} |A_{i+1} - A_i| \]
By precomputing the absolute differences in elevation between adjacent points, this can be efficiently calculated as an interval sum.
Issues with the Naive Approach
A straightforward approach would be to try all intervals \([l, r]\) and check whether the total elevation difference is at least \(K\). However, the number of intervals is \(O(N^2)\), and since \(N\) can be up to \(2 \times 10^5\), this is not practical (it would result in TLE).
Solution: Binary Search + Sliding Window
Since we want to find the minimum number of points (i.e., the interval length), we consider the decision problem: “Does there exist an interval with \(x\) points that satisfies the condition?” This can be solved using binary search.
Furthermore, for each number of points, we need to efficiently determine whether a qualifying interval exists. By using a prefix sum of the adjacent differences, we can compute any interval sum in \(O(1)\). Then, by using a sliding window to find the maximum interval sum among all fixed-length intervals and checking whether it is at least \(K\), each decision step can be performed in linear time.
Algorithm
Precompute the absolute differences in elevation between adjacent points into an array
diff: $\( \text{diff}[i] = |A_{i+1} - A_i| \)$Compute the prefix sum of
diffinto an arrayprefix: $\( \text{prefix}[i] = \sum_{j=0}^{i-1} \text{diff}[j] \)$Perform binary search on the number of points \(len\):
- Determine whether there exists an interval sum of
diffwith length \(len - 1\) that is at least \(K\). - This amounts to checking whether there exist \(i, j\) (where \(j - i = len - 1\)) such that
prefix[j] - prefix[i] >= K, using a sliding window.
- Determine whether there exists an interval sum of
Output the minimum \(len\) that satisfies the condition. If none exists, output
-1.
Complexity
- Time complexity: \(O(N \log N)\)
Each binary search step performs a linear-time check using the sliding window, so the overall complexity is \(O(N \log N)\). - Space complexity: \(O(N)\)
Thediffandprefixarrays use \(O(N)\) memory.
Implementation Notes
Use prefix sums to efficiently compute interval sums.
Set the binary search range from
1toN, and be careful with the casemid = 1(since the interval length becomes 0, making it always impossible).Use the sliding window to efficiently compute the maximum interval sum and perform the condition check.
Source Code
import sys
from itertools import accumulate
def main():
import sys
input = sys.stdin.read
data = input().split()
N = int(data[0])
K = int(data[1])
A = list(map(int, data[2:]))
# Compute the absolute differences
diff = [abs(A[i+1] - A[i]) for i in range(N-1)]
# If K is 0, we can always take a single point
if K == 0:
print(1)
return
# Prefix sums of differences
prefix = [0] + list(accumulate(diff))
# Binary search on the answer (number of points in route)
# The number of points is len = r - l + 1 => r - l = len - 1
# So total difference is prefix[r] - prefix[l]
# We want to find minimal len such that there exists r-l = len-1 with prefix[r] - prefix[l] >= K
def possible(length):
# Check if there's any subarray of consecutive differences of length (length-1)
# whose sum is at least K
if length == 1:
return False # Since K > 0 and sum of 0 terms is 0
window_len = length - 1
if window_len > len(prefix) - 1:
return False
for i in range(len(prefix) - window_len):
j = i + window_len
if prefix[j] - prefix[i] >= K:
return True
return False
# More efficient check using sliding window minimum
def possible_efficient(length):
if length == 1:
return False
window_len = length - 1
if window_len > len(prefix) - 1:
return False
for i in range(len(prefix) - window_len):
j = i + window_len
if prefix[j] - prefix[i] >= K:
return True
return False
# Even more efficient: monotonic queue approach for large inputs -> but since we're doing binary search
# over answers and checking feasibility each time, let's optimize the feasibility check.
left = 1
right = N
answer = -1
while left <= right:
mid = (left + right) // 2
# We want to check if there's a subarray of 'diff' of length (mid - 1) with sum >= K
window_size = mid - 1
found = False
if window_size == 0:
# mid=1 => only one point => sum = 0 < K (since K>0), so not valid
found = False
elif window_size > len(diff):
found = False
else:
# Sliding window maximum of size window_size in diff array
current_sum = sum(diff[:window_size])
if current_sum >= K:
found = True
else:
for i in range(window_size, len(diff)):
current_sum += diff[i] - diff[i - window_size]
if current_sum >= K:
found = True
break
if found:
answer = mid
right = mid - 1
else:
left = mid + 1
print(answer)
if __name__ == "__main__":
main()
This editorial was generated by qwen3-coder-480b.
posted:
last update: