C - カードの重ね置き / Stacking Cards Editorial by admin
DeepSeek V3Overview
This problem requires simulating card addition, removal, and inspection operations on a stack, and for each inspection operation, finding the most recent previous inspection operation that yielded the same XOR value.
Analysis
A naive approach of computing the XOR of the entire card stack for each operation would require scanning all cards for every inspection operation, resulting in \(O(N^2)\) time in the worst case, which would TLE under the constraint \(N \leq 2 \times 10^5\).
The key observation is that card operations follow a stack structure (LIFO). The addition operation (PUT) pushes a card onto the stack, and the removal operation (REMOVE) takes off the top card. Due to this property, the current XOR value can be easily computed from the previous XOR value and the new card’s value (on addition: current_xor ^ c; on removal: current_xor ^ removed_card).
Additionally, by recording the XOR value obtained at each inspection operation and managing the most recent occurrence position using a dictionary, we can efficiently search for past inspection operations with the same value.
Algorithm
- Initialize the current XOR value
current_xorto 0 - Process each operation in order:
PUT c: Apply XOR withctocurrent_xorREMOVE: Apply XOR with the value of the removed card (top of stack) tocurrent_xorLOOK: Record the currentcurrent_xor, and look up the most recent occurrence position in the dictionary. If found, add that number to the results; otherwise, add -1. Update the dictionary entry for that value with the current inspection operation number
- Output all inspection operation results
The stack itself is used to hold card values, but the XOR value calculation uses incremental updates without scanning the entire stack.
Complexity
- Time complexity: \(O(N)\)
- Each operation can be processed in constant time (dictionary operations are \(O(1)\) on average)
- Space complexity: \(O(N)\)
- The sizes of the stack and dictionary are proportional to at most \(N\)
Implementation Notes
Leveraging XOR properties: XORing the same value twice results in 0 (allowing removal operations to cancel out values)
The dictionary
xor_to_last_indexmanages the most recent occurrence position of each XOR valueThe inspection operation number is tracked with
look_countResults are stored as tuples and output all at once at the end
Source Code
import sys
def main():
data = sys.stdin.read().splitlines()
n = int(data[0])
events = data[1:1+n]
stack = []
xor_stack = []
current_xor = 0
results = []
xor_to_last_index = {}
look_count = 0
for event in events:
parts = event.split()
if parts[0] == 'PUT':
c = int(parts[1])
stack.append(c)
current_xor ^= c
xor_stack.append(current_xor)
elif parts[0] == 'REMOVE':
removed = stack.pop()
current_xor ^= removed
xor_stack.append(current_xor)
elif parts[0] == 'LOOK':
look_count += 1
v = current_xor
if v in xor_to_last_index:
results.append((look_count, xor_to_last_index[v]))
else:
results.append((look_count, -1))
xor_to_last_index[v] = look_count
for idx, val in results:
print(val)
if __name__ == "__main__":
main()
This editorial was generated by deepseekv3.
posted:
last update: