D - 電球パネルの一斉制御 / Simultaneous Control of Light Bulb Panels Editorial by admin
Qwen3-Coder-480B概要
連続する \(K\) 個の電球の状態を一斉に反転させることを繰り返して、すべての電球を点灯状態にできるか判定し、できる場合は最小操作回数を求めます。
考察
この問題では、操作によって連続する \(K\) 個の電球の状態が同時に変化します。したがって、ある位置の電球が最終的にどうなるかは、その位置を含むすべての操作の回数に依存します。
素朴な方法として、実際にシミュレーションしながらすべての電球を点灯させていくことを考えますが、単純に毎回 \(K\) 個の要素を反転させると、最悪の場合 \(O(N^2)\) の計算量になり、\(N\) が最大 \(2 \times 10^5\) なので間に合いません。
重要な観察は、操作の影響を累積的に管理することで、現在の電球の状態を高速に求められることです。つまり、ある操作の開始位置と終了位置を記録しておき、範囲の影響を差分更新(imos法のような考え方)で管理すれば、各電球の現在の状態を \(O(1)\) で求めることができます。
また、左から順番に処理していき、ある位置が消灯状態であれば、その位置から始まる長さ \(K\) の区間に操作を行うのが最適です。なぜなら、その区間を後で操作しても結果は変わらないからです。ただし、区間が配列外に出る場合(つまり \(i + K > N\))は操作できないので、その時点で -1 を出力します。
アルゴリズム
- 各操作の影響を記録するために
flip_count配列を用意します(imos法風)。これは区間の開始と終了を記録するために使います。 current_flip変数で、現在の位置に影響を与えている操作の回数の偶奇(つまり反転回数の合計のmod 2)を管理します。- 左から順番に各電球を見ていき、その時点での状態(初期状態 XOR 現在の反転回数)が
1(消灯)であれば、その位置から始まる長さ \(K\) の区間に操作を行います。 - 操作を行う際は:
operationsをインクリメントcurrent_flipを反転flip_count[i + K]に反転操作を記録(区間の終了地点)
- 区間が範囲外になる場合は
-1を出力して終了。 - 最後に操作回数
operationsを出力。
計算量
- 時間計算量: \(O(N)\)
- 空間計算量: \(O(N)\)
実装のポイント
flip_countは区間の終端を記録する場所として \(N+1\) のサイズを確保する必要があります。current_flipは、flip_count[i]を反映して毎回更新する必要があります(差分更新)。- 電球の状態は XOR を使って簡潔に計算できます。
## ソースコード
```python
from collections import deque
def main():
import sys
input = sys.stdin.read
data = input().split()
N = int(data[0])
K = int(data[1])
A = list(map(int, data[2:]))
# 0: 点灯, 1: 消灯 → 目標はすべて0にする
# 各位置について、操作の影響を管理する
# 差分更新で効率的にシミュレーション
flip_count = [0] * (N + 1) # imos法で操作回数を記録
current_flip = 0
operations = 0
queue = deque()
for i in range(N):
current_flip ^= flip_count[i]
current_state = A[i] ^ current_flip
if current_state == 1: # 消灯状態なら反転が必要
if i + K > N:
print(-1)
return
# 区間 [i, i+K) に操作を適用
operations += 1
current_flip ^= 1
if i + K < N + 1:
flip_count[i + K] ^= 1
print(operations)
if __name__ == "__main__":
main()
この解説は qwen3-coder-480b によって生成されました。
posted:
last update: