C - 照明の切り替え / Switching the Lights Editorial by admin
Gemini 3.0 FlashOverview
Given \(N\) rooms (initially all lights off), we perform \(Q\) operations, each toggling the lights in a specified range \([L, R]\). The problem asks how many of the \(M\) specified meeting rooms have their lights on at the end.
Analysis
1. Checking the Constraints
Since the number of rooms \(N\) can be up to \(10^9\), it is impossible to manage the state of every room using an array. On the other hand, the number of operations \(Q\) and the number of meeting rooms \(M\) are around \(2 \times 10^5\), so we need to devise a solution focusing on these.
2. Conditions for Lights On/Off
Whether a room \(x\) is ultimately lit depends on “how many toggle operations (ranges \([L, R]\)) include that room \(x\)”. - If the number of operations is odd: the light is on - If the number of operations is even: the light is off
Therefore, the key is to efficiently count, for each meeting room \(B_i\), how many operations \([L_j, R_j]\) cover that room number.
3. Counting Covering Operations
The condition for room \(x\) to be included in range \([L, R]\) is \(L \leq x \leq R\). This can be reformulated as simultaneously satisfying the following \(2\) conditions: 1. The start point \(L\) of the range is at most \(x\) (\(L \leq x\)) 2. The end point \(R\) of the range is at least \(x\) (\(R \geq x\))
Let \(\mathcal{L}\) be the set of all start points and \(\mathcal{R}\) be the set of all end points of the operations. The number of operations that include room \(x\) can be computed as: - (Number of operations where \(L \leq x\)) \(-\) (Number of operations where \(R < x\))
This is because, among the operations whose start point is at most \(x\), those whose end point ends before \(x\) (less than \(x\)) do not actually cover room \(x\).
Algorithm
We use binary search to efficiently compute the number of covering operations for each meeting room.
- Store all operation start points \(L_i\) in a list
l_coordsand all end points \(R_i\) in a listr_coords. - Sort
l_coordsandr_coordsin ascending order to enable binary search. - For each meeting room \(B_i\), do the following:
- Use
bisect_rightto find how many values inl_coordsare at most \(B_i\) (the count of \(L \leq B_i\)). - Use
bisect_leftto find how many values inr_coordsare less than \(B_i\) (the count of \(R < B_i\)). - Compute the difference of these two numbers, and if it is odd, increment the count by \(1\).
- Use
- Output the final count.
Complexity
- Time Complexity: \(O((Q + M) \log Q)\)
- Sorting the operation ranges takes \(O(Q \log Q)\).
- Performing binary search for each meeting room (\(M\) rooms) takes \(O(M \log Q)\).
- Space Complexity: \(O(M + Q)\)
- Required to store the list of meeting rooms and the lists of operation ranges.
Implementation Notes
Fast I/O: Since \(M\) and \(Q\) can be large, in Python, using
sys.stdin.read().split()andsys.stdout.writecan reduce execution time.Choosing the right binary search function:
bisect_right(list, x): Suitable for counting the number of elements at most \(x\) (since it returns the insertion point to the right).bisect_left(list, x): Suitable for counting the number of elements less than \(x\) (since it returns the insertion point to the left).Source Code
import sys
from bisect import bisect_left, bisect_right
def main():
# 全ての入力を一度に読み込んでスペースで分割し、リスト化します。
# この方法はPythonにおいて大量の数値を読み込む際に効率的です。
input_data = sys.stdin.read().split()
if not input_data:
return
# N: 部屋の総数, M: 会議室の個数, Q: 操作の回数
# Nは最大10^9、MとQは最大2*10^5です。
n = int(input_data[0])
m = int(input_data[1])
q = int(input_data[2])
# B: 会議室の部屋番号のリスト
b = list(map(int, input_data[3:3+m]))
# 各操作の範囲 [L, R] の始点 L と終点 R を別々のリストに格納します。
l_coords = [0] * q
r_coords = [0] * q
current_idx = 3 + m
for i in range(q):
l_coords[i] = int(input_data[current_idx])
r_coords[i] = int(input_data[current_idx + 1])
current_idx += 2
# 二分探索を用いるため、LとRのリストをソートします。
l_coords.sort()
r_coords.sort()
lit_count = 0
# 各会議室について、いくつの操作範囲に含まれているかを計算します。
# 部屋 x が範囲 [L, R] に含まれる条件は L <= x かつ R >= x です。
for pos in b:
# count_l: 始点 L が会議室の番号 pos 以下である操作の数
count_l = bisect_right(l_coords, pos)
# count_r: 終点 R が会議室の番号 pos より小さい(posの手前で終わっている)操作の数
count_r = bisect_left(r_coords, pos)
# 会議室 pos を含む操作の総数は (count_l - count_r) となります。
# 操作回数が奇数であれば、その部屋の照明は最終的に「点灯」状態になります。
if (count_l - count_r) % 2 == 1:
lit_count += 1
# 会議室のうち点灯している部屋の個数を出力します。
sys.stdout.write(str(lit_count) + '\n')
if __name__ == '__main__':
main()
This editorial was generated by gemini-3-flash-preview.
posted:
last update: