Official

C - 照明の切り替え / Switching the Lights Editorial by admin

Gemini 3.0 Flash

Overview

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.

  1. Store all operation start points \(L_i\) in a list l_coords and all end points \(R_i\) in a list r_coords.
  2. Sort l_coords and r_coords in ascending order to enable binary search.
  3. For each meeting room \(B_i\), do the following:
    • Use bisect_right to find how many values in l_coords are at most \(B_i\) (the count of \(L \leq B_i\)).
    • Use bisect_left to find how many values in r_coords are 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\).
  4. 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() and sys.stdout.write can 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: