D - 配達圏内の売上合計 / Total Sales Within Delivery Range Editorial by admin
Claude 4.6 Opus (Thinking)Overview
This problem asks you to compute, for each delivery hub candidate, the total sales of stores within a certain range measured by Manhattan distance. By applying a coordinate transformation, the problem reduces to rectangular region queries, which can be solved efficiently using 2D prefix sums.
Analysis
Problem with the Naive Approach
Scanning all stores for each query results in \(O(NM)\) operations, requiring up to about \(10^{10}\) computations, which will TLE.
Key Insight: Coordinate Transformation of Manhattan Distance (45-Degree Rotation)
The region satisfying the Manhattan distance condition \(|X_i - P_j| + |Y_i - Q_j| \le K_j\) forms a diamond (rhombus) shape in the \((X, Y)\) coordinate system. This is difficult to handle, but the following coordinate transformation converts it into a rectangle:
\[u = x + y, \quad v = x - y\]
After this transformation, the Manhattan distance condition becomes a Chebyshev distance condition (the maximum of the absolute differences along each axis):
\[|X_i - P_j| + |Y_i - Q_j| \le K_j \iff \max(|u_i - u_j|, |v_i - v_j|) \le K_j\]
This is an axis-aligned square (rectangle) in the \((u, v)\) plane. Specifically:
\[u_j - K_j \le u_i \le u_j + K_j \quad \text{and} \quad v_j - K_j \le v_i \le v_j + K_j\]
Concrete example: Store \((3, 2)\), hub \((1, 1)\), \(K=3\) - Manhattan distance: \(|3-1|+|2-1|=3 \le 3\) → delivery is possible - After transformation: Store \(u=5, v=1\), hub \(u=2, v=0\) - \(\max(|5-2|, |1-0|) = 3 \le 3\) → same result
Sum over a Rectangular Region → 2D Prefix Sums
The sum of values within a rectangular region can be computed in \(O(1)\) by precomputing a 2D prefix sum.
Algorithm
- Coordinate transformation: Transform each store’s coordinates \((x, y)\) to \((u, v) = (x+y, x-y+1000)\) (adding \(1000\) to \(v\) to ensure non-negativity)
- Placement on grid: Add each store’s sales to the transformed coordinates. Since \(u\) ranges over \([0, 2000]\) and \(v\) ranges over \([0, 2000]\), prepare a grid of size \(2001 \times 2001\)
- Build the 2D prefix sum: Precompute \(\text{psum}[i][j] = \sum_{0 \le a \le i, 0 \le b \le j} \text{grid}[a][b]\)
- Answer each query: From the hub \((p, q)\) and distance \(k\), compute the rectangular range and obtain the sum in \(O(1)\) using the prefix sum
Computing the rectangular region sum using the prefix sum (inclusion-exclusion principle):
\[\text{ans} = \text{psum}[u_h][v_h] - \text{psum}[u_l\!-\!1][v_h] - \text{psum}[u_h][v_l\!-\!1] + \text{psum}[u_l\!-\!1][v_l\!-\!1]\]
Complexity
- Time complexity: \(O(S^2 + M)\) (\(S = 2001\) is the grid size. Building the prefix sum takes \(O(S^2)\), and each query takes \(O(1)\))
- Space complexity: \(O(S^2)\)
Implementation Notes
Offset for \(v\): Since \(v = x - y\) can be negative (minimum \(-1000\)), add \(+1000\) to make it non-negative
Range clipping: If the query rectangle extends outside the grid, clamp it to \([0, 2000]\) using \(\max\) and \(\min\)
Prefix sum boundary handling: When \(u_l = 0\) or \(v_l = 0\), add conditional checks to avoid accessing index \(-1\)
Fast input: By reading all input at once with
sys.stdin.buffer.read(), the solution runs sufficiently fast even in PythonSource Code
import sys
def main():
input_data = sys.stdin.buffer.read().split()
idx = 0
N = int(input_data[idx]); idx += 1
M = int(input_data[idx]); idx += 1
SIZE = 2001
grid = [[0] * (SIZE + 1) for _ in range(SIZE + 1)]
for i in range(N):
x = int(input_data[idx]); idx += 1
y = int(input_data[idx]); idx += 1
c = int(input_data[idx]); idx += 1
u = x + y
v = x - y + 1000
grid[u][v] += c
# Build 2D prefix sum
psum = [[0] * (SIZE + 1) for _ in range(SIZE + 1)]
for i in range(SIZE):
row_sum = 0
for j in range(SIZE):
row_sum += grid[i][j]
psum[i][j] = row_sum + (psum[i - 1][j] if i > 0 else 0)
out = []
for j in range(M):
p = int(input_data[idx]); idx += 1
q = int(input_data[idx]); idx += 1
k = int(input_data[idx]); idx += 1
u_lo = p + q - k
u_hi = p + q + k
v_lo = p - q - k + 1000
v_hi = p - q + k + 1000
u_lo = max(u_lo, 0)
u_hi = min(u_hi, SIZE - 1)
v_lo = max(v_lo, 0)
v_hi = min(v_hi, SIZE - 1)
if u_lo > u_hi or v_lo > v_hi:
out.append('0')
continue
ans = psum[u_hi][v_hi]
if u_lo > 0:
ans -= psum[u_lo - 1][v_hi]
if v_lo > 0:
ans -= psum[u_hi][v_lo - 1]
if u_lo > 0 and v_lo > 0:
ans += psum[u_lo - 1][v_lo - 1]
out.append(str(ans))
sys.stdout.write('\n'.join(out) + '\n')
main()
This editorial was generated by claude4.6opus-thinking.
posted:
last update: