C - スイッチと電球 / Switches and Light Bulbs Editorial by admin Editorial for printing
Gemini 3.8 Flash (High)Overview
On an \(H \times W\) grid, \(Q\) operations are performed where a switch at a specified cell is pressed, toggling the light bulbs at that cell and its four adjacent cells (up, down, left, right). The problem asks for the state of the light bulb in each cell after all operations are completed.
Analysis
Key Observations
This problem has \(2\) key properties regarding the switches and the light bulb toggle operations:
- The order of operations does not affect the result (commutativity)
- Pressing the same switch \(2\) times returns to the original state (parity)
The final state of each light bulb \((r, c)\) depends solely on whether the group of switches that toggle that bulb was pressed an odd or even total number of times. The switches that toggle the light bulb at \((r, c)\) are the switch at cell \((r, c)\) itself and the switches at its adjacent cells in the four directions (up, down, left, right), for a maximum of \(5\) locations.
Naive Approach and Its Issues
If we traverse \(5\) cells and update their states for every query, the per-operation overhead can become significant depending on the implementation language and data structures. Furthermore, performing boundary checks or string generation on each query introduces heavy constant-factor overhead, increasing the risk of getting Time Limit Exceeded (TLE).
Solution
Instead of updating the light bulbs on each query, we simply record how many times each switch was pressed. Furthermore, pressing a switch an even number of times is practically equivalent to pressing it \(0\) times, and an odd number of times is equivalent to pressing it \(1\) time. Therefore, the only value we need to record is the parity of the number of presses (\(0\) or \(1\)) for each switch.
- Process all queries to determine the parity of the number of presses for each switch.
- Then, for each light bulb \((r, c)\), compute the total parity (exclusive OR: \(\text{XOR}\)) of the switch press counts across the \(5\) cells (itself and its four adjacent neighbors) to determine all at once whether its initial state should be toggled.
This allows us to process the queries and compute the final states independently and efficiently.
Algorithm
Prepare an array to record the parity of switch presses Initialize an array
cntof size \((H + 2) \times (W + 2)\) with \(0\). By adding a 1-cell margin (sentinel/padding) around the perimeter of the grid, we can uniformly access the four adjacent cells without worrying about out-of-bounds access, even for edge cells.Process queries For each of the \(Q\) operations, toggle the state of the switch at the given cell \((R_k, C_k)\) (
cnt[R_k][C_k] ^= 1).Determine the state of each light bulb For each cell \((r, c)\) (\(1 \leq r \leq H, 1 \leq c \leq W\)), calculate the XOR sum of the press parities of the switch itself and the switches in the four adjacent cells: $\(\text{flip} = cnt[r][c] \oplus cnt[r-1][c] \oplus cnt[r+1][c] \oplus cnt[r][c-1] \oplus cnt[r][c+1]\)$
- If \(\text{flip} = 1\): Toggle the initial state (
0\(\to\)1,1\(\to\)0) - If \(\text{flip} = 0\): Keep the initial state unchanged
- If \(\text{flip} = 1\): Toggle the initial state (
Concatenate the results of all rows and output.
Complexity
- Time Complexity: \(O(HW + Q)\)
- Processing the queries takes \(O(Q)\) time.
- Computing the final board takes \(O(HW)\) time, as we check the surrounding \(5\) cells for each of the \(H \times W\) cells.
- Since \(H \times W \leq 10^6\) and \(Q \leq 10^5\), this comfortably runs within the time limit.
- Space Complexity: \(O(HW)\)
- It uses \(O(HW)\) memory to store the grid information of size \((H + 2) \times (W + 2)\) and the answer strings.
Implementation Details
Omitting boundary checks with sentinels (padding) By adding a 1-row/1-column margin around the top, bottom, left, and right of the grid, we eliminate
ifstatements for boundary checks such as “\(1 \leq r \leq H\) and \(1 \leq c \leq W\)”, keeping the code concise while improving execution speed.Flat representation using a 1D array In Python, managing the grid as a flat 1D array (with index
r * (W + 2) + c) allows for faster memory access compared to using a 2Dlist.Optimization using
bytearrayand ASCII code XOR The ASCII code for the character'0'is \(48\) (...00in binary), and for'1'it is \(49\) (...01in binary). Since only the least significant bit differs, toggling between'0'and'1'can be performed very quickly simply by applying the \(\text{XOR}\) operation between the character code and \(\text{flip}\) (\(0\) or \(1\)) (e.g., \(48 \oplus 1 = 49\), \(49 \oplus 1 = 48\)).Source Code
import sys
def main():
input_data = sys.stdin.read().split()
if not input_data:
return
H = int(input_data[0])
W = int(input_data[1])
ptr = 2
S = input_data[ptr : ptr + H]
ptr += H
Q = int(input_data[ptr])
ptr += 1
W2 = W + 2
cnt = bytearray((H + 2) * W2)
RC = input_data[ptr:]
for i in range(0, 2 * Q, 2):
r = int(RC[i])
c = int(RC[i + 1])
cnt[r * W2 + c] ^= 1
ans = []
for r in range(1, H + 1):
s_row = S[r - 1].encode("ascii")
res_row = bytearray(W)
base = r * W2
for c in range(1, W + 1):
idx = base + c
flip = (
cnt[idx]
^ cnt[idx - 1]
^ cnt[idx + 1]
^ cnt[idx - W2]
^ cnt[idx + W2]
)
res_row[c - 1] = s_row[c - 1] ^ flip
ans.append(res_row.decode("ascii"))
sys.stdout.write("\n".join(ans) + "\n")
if __name__ == "__main__":
main()
This editorial was generated by gemini-3.8-flash-high.
posted:
last update: