B - ロボットの宝集め / Robot's Treasure Collection 解説 by admin
gpt-5.5-highOverview
The instruction sequence \(S\) is updated over time, and for each query we need to find “the score when the robot executes \(S\) from its initial state.”
Since the constraint \(KQ \leq 2 \times 10^7\) holds, we can simulate the entire instruction sequence for each query.
Analysis
Each time a query operation 2 is issued, the robot starts execution from the following initial state:
- Located in room \(1\)
- Score is \(0\)
- All treasures are uncollected
Therefore, for each query, we can find the answer by simulating the instruction sequence \(S\) from the beginning.
At first glance, you might want to reinitialize the array representing “whether each room’s treasure has been collected” every time a query is issued.
However, since the number of rooms \(N\) can be up to \(2 \times 10^5\), initializing an array of length \(N\) for each query adds an extra \(O(N)\) cost.
For example, if the number of queries is \(K\), naively reinitializing every time results in an overall cost of
\(O(K(N + Q))\)
On the other hand, this problem has the constraint \(KQ \leq 2 \times 10^7\), meaning the simulation part \(O(KQ)\) is designed to fit within the time limit.
Therefore, it is important to perform the initialization of treasure collection states efficiently.
To achieve this, we use a “timestamp” technique.
For each room \(i\), we record in seen[i] which query last collected the treasure from that room.
If the current query number is stamp, then:
- If
seen[i] == stamp, the treasure in room \(i\) has already been collected during this query - If
seen[i] != stamp, the treasure in room \(i\) has not yet been collected during this query
This eliminates the need to reinitialize the entire array for each query.
Algorithm
To allow modifications to the instruction sequence \(S\), we manage it as a bytearray instead of a string.
Each operation is processed as follows.
Operation 1 p c
Change the \(p\)-th character of the instruction sequence \(S\) to \(c\).
This simply overwrites one element of the array, so it runs in \(O(1)\).
Operation 2
Simulate the current instruction sequence from start to end.
Prepare the following variables:
pos: the current room, managed in \(0\)-indexed formscore: the current scorestamp: the current query numberseen[i]: the query number when the treasure in room \(i\) was last collected
During simulation, process each instruction character one by one:
L:- If
pos > 0, thenpos -= 1
- If
R:- If
pos < N - 1, thenpos += 1
- If
P:- If
seen[pos] != stamp, the treasure has not yet been collected in this query - Set
seen[pos] = stampand addscore += A[pos]
- If
B:- Set
pos = 0
- Set
Finally, output score.
For example, even if P is executed multiple times in the same room, since seen[pos] == stamp will hold after the first time, the score is only incremented on the first occurrence.
Complexity
Let \(K\) be the number of operation 2 queries.
- Time complexity: \(O(M + KQ)\)
- Each update operation takes \(O(1)\)
- Each query operation takes \(O(Q)\)
- Since \(KQ \leq 2 \times 10^7\) by the constraint, this is sufficiently fast
- Space complexity: \(O(N + Q)\)
- \(O(N)\) for managing treasure collection states
- \(O(Q)\) for storing the instruction sequence
Implementation Notes
Room numbers are \(1\)-indexed in the input, but using \(0\)-indexed in the implementation makes things easier to handle.
Initializing with
seen = [0] * Nfor each query may be slow. Instead, manage it by incrementingstamp.Since the instruction sequence is updated, using a
bytearrayinstead of a regular Python string allows efficient single-character modifications.The score can be as large as \(N \times 10^9\), so 64-bit integers are required. In Python, there is no need to worry about integer overflow.
Source Code
import sys
def main():
input = sys.stdin.buffer.readline
N, Q, M = map(int, input().split())
A = list(map(int, input().split()))
S = bytearray(input().strip())
seen = [0] * N
stamp = 0
n_last = N - 1
L = ord('L')
R = ord('R')
P = ord('P')
B = ord('B')
ans = []
for _ in range(M):
line = input().split()
if line[0] == b'1':
p = int(line[1]) - 1
S[p] = line[2][0]
else:
stamp += 1
pos = 0
score = 0
for c in S:
if c == P:
if seen[pos] != stamp:
seen[pos] = stamp
score += A[pos]
elif c == R:
if pos < n_last:
pos += 1
elif c == L:
if pos:
pos -= 1
else:
pos = 0
ans.append(str(score))
sys.stdout.write("\n".join(ans))
if __name__ == "__main__":
main()
This editorial was generated by gpt-5.5-high.