D - 荷物運びの道 / The Path of Carrying Luggage 解説 by admin
Claude 4.6 Opus (Thinking)Overview
This problem involves visiting warehouses lined up in a row from west to east in order, stopping at the warehouse where the cumulative weight exceeds the upper limit \(K\). We need to compute the stopping warehouse number \(f(s)\) for each starting point and quickly answer range sum queries.
Analysis
Rephrasing the Problem
Starting from warehouse \(s\), you pick up items in order \(A_s, A_{s+1}, \ldots\). You stop at warehouse \(t\) where the cumulative weight first exceeds \(K\). If you reach warehouse \(N\) without exceeding the limit, then \(f(s) = N\).
The cumulative weight can be expressed using prefix sums. Define \(P[i] = A_1 + A_2 + \cdots + A_i\) (with \(P[0] = 0\)). Then the total weight of items from warehouse \(s\) to warehouse \(t\) is:
\[A_s + A_{s+1} + \cdots + A_t = P[t] - P[s-1]\]
Therefore, \(f(s)\) can be defined as follows:
\(f(s)\) is the smallest \(t \geq s\) satisfying \(P[t] - P[s-1] > K\), i.e., \(P[t] > P[s-1] + K\). If no such \(t\) exists with \(t \leq N\), then \(f(s) = N\).
Issues with the Naive Approach
For each starting point \(s\), checking warehouses one by one to see if the cumulative weight exceeds \(K\) takes \(O(N)\) in the worst case. Across all starting points this becomes \(O(N^2)\), and with queries on top, it won’t be fast enough.
The Key: Binary Search
Since \(A_i \geq 1\), \(P\) is monotonically non-decreasing. Therefore, the smallest \(t\) satisfying \(P[t] > P[s-1] + K\) can be found in \(O(\log N)\) using binary search.
Handling Queries
After precomputing \(f(s)\) for all \(s\), we build a prefix sum of \(f\): \(Sf[i] = f[1] + f[2] + \cdots + f[i]\). Then each query \(\sum_{s=L}^{R} f(s) = Sf[R] - Sf[L-1]\) can be answered in \(O(1)\).
Algorithm
Build the prefix sum: Compute \(P[0] = 0\), \(P[i] = P[i-1] + A[i]\).
Compute \(f(s)\) (binary search for each \(s\)):
- Set \(\text{target} = P[s-1] + K\).
- If \(P[N] \leq \text{target}\), then we can reach warehouse \(N\), so \(f(s) = N\).
- Otherwise, use binary search to find the smallest \(t\) (\(s \leq t \leq N\)) such that \(P[t] > \text{target}\), and set \(f(s) = t\).
Example: For \(N=5\), \(K=7\), \(A = [3, 2, 4, 1, 5]\), we have \(P = [0, 3, 5, 9, 10, 15]\). - \(s=1\): target \(= 0 + 7 = 7\). Since \(P[3]=9 > 7\) and \(P[2]=5 \leq 7\), we get \(f(1) = 3\). - \(s=3\): target \(= 5 + 7 = 12\). Since \(P[5]=15 > 12\) and \(P[4]=10 \leq 12\), we get \(f(3) = 5\).
Build the prefix sum of \(f\): \(Sf[i] = Sf[i-1] + f[i]\).
Answer queries: For each query \((L_j, R_j)\), output \(Sf[R_j] - Sf[L_j - 1]\).
Complexity
- Time complexity: \(O(N \log N + Q)\)
- Computing \(f(s)\) uses binary search \(O(\log N)\) × \(N\) times = \(O(N \log N)\)
- Each query is \(O(1)\) using prefix sums
- Space complexity: \(O(N)\)
- The prefix sum arrays \(P\), \(f\), and \(Sf\) each use \(O(N)\)
Implementation Notes
Since \(K\) can be up to \(10^{15}\) and the sum of \(A_i\) can be up to approximately \(2 \times 10^{14}\), 64-bit integers must be used (Python handles this automatically).
The prefix sum \(P\) being monotonically non-decreasing is a prerequisite for binary search. This is guaranteed since \(A_i \geq 1\).
The binary search range is \([s, N]\). Note that we only search from \(s\) onward, not the entire array.
For fast I/O, we read all input at once using
sys.stdin.buffer.read()and output all at once usingsys.stdout.write().Source Code
import sys
from bisect import bisect_right
def main():
input_data = sys.stdin.buffer.read().split()
idx = 0
N = int(input_data[idx]); idx += 1
K = int(input_data[idx]); idx += 1
Q = int(input_data[idx]); idx += 1
A = [0] * (N + 1)
for i in range(1, N + 1):
A[i] = int(input_data[idx]); idx += 1
# prefix sum: P[0] = 0, P[i] = A[1] + ... + A[i]
P = [0] * (N + 1)
for i in range(1, N + 1):
P[i] = P[i - 1] + A[i]
# f(s): starting from warehouse s, find the warehouse where we stop
# We accumulate A[s] + A[s+1] + ... + A[t] = P[t] - P[s-1]
# We stop at t if P[t] - P[s-1] > K, i.e., P[t] > P[s-1] + K
# If no such t <= N, then f(s) = N
# Otherwise f(s) = smallest t >= s such that P[t] > P[s-1] + K
# Compute f(s) for all s using binary search
f = [0] * (N + 2) # f[1..N]
for s in range(1, N + 1):
target = P[s - 1] + K
# Find smallest t in [s, N] such that P[t] > target
# P is non-decreasing, so we can binary search
# bisect_right finds insertion point for target in P[s..N]
# We want first index where P[t] > target
lo, hi = s, N
result = N # default: reach warehouse N
if P[N] <= target:
f[s] = N
else:
# binary search for smallest t in [s, N] with P[t] > target
lo, hi = s, N
while lo < hi:
mid = (lo + hi) // 2
if P[mid] > target:
hi = mid
else:
lo = mid + 1
f[s] = lo
# Now we need to answer Q queries: sum of f(L) + f(L+1) + ... + f(R)
# Precompute prefix sums of f
Sf = [0] * (N + 2)
for i in range(1, N + 1):
Sf[i] = Sf[i - 1] + f[i]
out = []
for _ in range(Q):
L = int(input_data[idx]); idx += 1
R = int(input_data[idx]); idx += 1
out.append(str(Sf[R] - Sf[L - 1]))
sys.stdout.write('\n'.join(out) + '\n')
main()
This editorial was generated by claude4.6opus-thinking.
投稿日時:
最終更新: