E - 散歩とバリケード / A Walk and Barricades 解説 by admin
Claude 4.6 Opus (Thinking)Overview
Starting from coordinate \(0\) on a number line, you sequentially consider \(N\) movement plans, selecting those that do not collide with barricades, and maximize the final coordinate. We use Python’s arbitrary-precision integers as bitsets to manage the set of reachable coordinates in bulk.
Analysis
The range of reachable coordinates is narrow
Since the total sum of absolute values of each plan’s displacement satisfies \(\sum |D_i| \leq 5 \times 10^4\), no matter which plans are selected, the reachable coordinates are confined to the range \([-50000, 50000]\). This is at most \(100001\) integer coordinates.
What about a naive DP?
Consider a DP that manages “the set of currently reachable coordinates.” For each plan, we need to check whether each element of the set “collides with a barricade.” Letting the set size be \(S\) (at most \(100001\)) and the number of plans be \(N\), a naive approach takes \(O(S \times |D_i|)\) per plan, totaling \(O(S \times \sum |D_i|)\). This is roughly \(100001 \times 50000 = 5 \times 10^9\), which will TLE with straightforward looping.
Speedup using bitsets
Python’s arbitrary-precision integers support bitwise operations and can be used as bitsets where 1 bit corresponds to 1 coordinate. Bit shifts and OR operations are internally processed in word-size units of \(w = 64\) bits, so they run in \(O(S/w)\), reducing the constant factor by approximately \(1/64\).
Algorithm
Set OFFSET = 50000, and map coordinate \(x\) to bit position \(x + \text{OFFSET}\).
Build the barricade bitset
barricade_bits: If coordinate \(X_j\) is within range, set bit \((X_j + \text{OFFSET})\).Initialize the reachable set
reachable: Set only bit \(\text{OFFSET}\) (coordinate \(0\)).For each plan \(d = D_i\):
- If \(d > 0\): Moving from coordinate \(s\) to \(s + d\). The collision condition is “there exists a barricade at any of \(s, s+1, \ldots, s+d\).”
- Compute
blocked: OR together the results of right-shiftingbarricade_bitsby \(0, 1, \ldots, d\) bits. Then bit \(p\) ofblockedrepresents “whether there is a barricade in the interval from coordinate \(p\) to \(p + d\).” can_move = reachable & ~blocked(the set of coordinates that are reachable and do not collide)reachable |= (can_move << d)(add the coordinates after movement)
- Compute
- If \(d < 0\) (\(ad = -d\)): Similarly, compute
blockedusing left shifts, and represent the movement using right shifts.
- If \(d > 0\): Moving from coordinate \(s\) to \(s + d\). The collision condition is “there exists a barricade at any of \(s, s+1, \ldots, s+d\).”
The answer is the position of the most significant bit of
reachableminus OFFSET.
Concrete example: If the reachable coordinates are \(\{-1, 0, 2\}\), \(d = 3\), and there is a barricade at coordinate \(1\), then coordinates \(-1\) and \(0\) are blocked because their intervals \([-1, 2]\) and \([0, 3]\) contain the barricade (coordinate \(1\)). Only coordinate \(2\) can move, reaching coordinate \(5\).
Complexity
- Time complexity: \(O\!\left(\dfrac{S \cdot \sum |D_i|}{w}\right)\)
- With \(S = 100001\), \(\sum |D_i| \leq 50000\), \(w = 64\), this is roughly \(7.8 \times 10^7\)
- Space complexity: \(O(S + M)\)
- The bitset requires \(O(S/w)\) words, and reading the barricades requires \(O(M)\)
Implementation Notes
Python’s arbitrary-precision integers serve as bitsets: Operations equivalent to C++’s
bitsetcan be realized in Python through bitwise operations on large integers.<<,>>,|,&,~all operate efficiently at the word level.Ignore barricades outside the range: Barricades at coordinates outside \([-50000, 50000]\) are unreachable and can be skipped.
Construction of
blocked: Performing \(|d|+1\) shift-and-OR operations to collectively determine barricade existence within an interval is the core technique. This eliminates the need to check each coordinate independently.Final answer:
reachable.bit_length() - 1gives the most significant bit position (= maximum reachable coordinate + OFFSET), so subtracting OFFSET yields the coordinate.Source Code
import sys
def main():
data = sys.stdin.buffer.read().split()
idx = 0
N = int(data[idx]); idx += 1
M = int(data[idx]); idx += 1
D = []
for i in range(N):
D.append(int(data[idx])); idx += 1
OFFSET = 50000
barricade_bits = 0
for j in range(M):
x = int(data[idx]); idx += 1
if -50000 <= x <= 50000:
barricade_bits |= (1 << (x + OFFSET))
reachable = 1 << OFFSET # start at position 0
for d in D:
if d > 0:
blocked = 0
for k in range(d + 1):
blocked |= (barricade_bits >> k)
can_move = reachable & ~blocked
reachable |= (can_move << d)
else:
ad = -d
blocked = 0
for k in range(ad + 1):
blocked |= (barricade_bits << k)
can_move = reachable & ~blocked
reachable |= (can_move >> ad)
# Maximum set bit gives maximum reachable position
ans = reachable.bit_length() - 1 - OFFSET
print(ans)
main()
This editorial was generated by claude4.6opus-thinking.
投稿日時:
最終更新: