题解:AtCoder AT_awc0022_d Simultaneous Control of Light Bulb Panels
【题目来源】
AtCoder:D - Simultaneous Control of Light Bulb Panels
【题目描述】
Takahashi has a decorative panel with \(N\) light bulbs arranged in a row. The bulbs are numbered from \(1\) to \(N\) from left to right, and each bulb is in one of two states: "on" or "off".
高桥有一块装饰面板,上面有 \(N\) 个灯泡排成一行。灯泡从左到右编号为 \(1\) 到 \(N\),每个灯泡处于两种状态之一:"亮"或"灭"。
The initial state of each bulb is given by an integer \(A_i\). When \(A_i = 0\), bulb \(i\) is on, and when \(A_i = 1\), bulb \(i\) is off.
每个灯泡的初始状态由一个整数 \(A_i\) 给出。当 \(A_i = 0\) 时,灯泡 \(i\) 是亮的;当 \(A_i = 1\) 时,灯泡 \(i\) 是灭的。
Takahashi can perform the following operation any number of times (possibly zero):
高桥可以执行以下操作任意多次(包括零次):
- Choose an integer \(i\) (\(1 \leq i \leq N - K + 1\)) and toggle the states of bulbs \(i, i+1, \ldots, i+K-1\). That is, among these \(K\) consecutive bulbs, those that are on are turned off, and those that are off are turned on.
选择一个整数 \(i\)(\(1 \leq i \leq N - K + 1\)),并切换灯泡 \(i, i+1, \ldots, i+K-1\) 的状态。也就是说,在这 \(K\) 个连续的灯泡中,原本亮的会熄灭,原本灭的会点亮。
The value of \(i\) chosen in each operation can be decided freely each time, and it is allowed to choose the same value as before.
每次操作中选择的 \(i\) 值可以自由决定,并且允许选择与之前相同的值。
Takahashi wants to turn all bulbs on (that is, reach the state where \(A_i = 0\) for all \(i\)). Determine whether this is possible, and if so, find the minimum number of operations required.
高桥希望将所有灯泡点亮(即达到所有 \(i\) 的 \(A_i = 0\) 的状态)。判断这是否可能,如果可能,求所需的最少操作次数。
【输入】
\(N\) \(K\)
\(A_1\) \(A_2\) \(\ldots\) \(A_N\)
- The first line contains an integer \(N\) representing the number of bulbs and an integer \(K\) representing the number of bulbs toggled in one operation, separated by a space.
- The second line contains integers \(A_1, A_2, \ldots, A_N\) representing the initial state of each bulb, separated by spaces.
- When \(A_i = 0\), bulb \(i\) is on.
- When \(A_i = 1\), bulb \(i\) is off.
【输出】
If it is possible to turn all bulbs on, output the minimum number of operations required in one line.
If it is impossible, output -1 in one line.
【输入样例】
5 3
0 1 1 1 0
【输出样例】
1
【核心思想】
-
问题分析:给定 \(N\) 个灯泡的初始状态(\(0\) 表示亮,\(1\) 表示灭),每次操作可以翻转连续 \(K\) 个灯泡的状态。目标是使所有灯泡都亮(全 \(0\)),求最少操作次数或判断无解。这是一个差分数组 + 贪心问题,关键在于如何高效记录和操作区间翻转。
-
算法选择:
- 差分数组(Difference Array):用差分数组记录区间翻转操作的影响,将区间更新转化为单点更新
- 贪心策略:从左到右遍历,遇到灭的灯泡就立即翻转(贪心选择),确保前面的灯泡不再被影响
- 前缀和还原:通过差分数组的前缀和计算每个位置的累积翻转次数
-
关键步骤:
- 初始化差分数组:
diff[i]用于记录在位置 \(i\) 开始的翻转操作次数(模 \(2\)) - 从左到右贪心遍历(\(i\) 从 \(1\) 到 \(N\)):
- 计算当前累积影响:
diff[i] = (diff[i-1] + diff[i]) % 2,表示位置 \(i\) 被前面操作翻转的次数(模 \(2\)) - 计算当前状态:
state = a[i] ^ diff[i],原始状态异或累积影响 - 判断是否需要翻转:
- 若
state == 0:灯泡已亮,跳过 - 若
state == 1:灯泡仍灭,需要翻转- 检查可行性:若 \(i + K - 1 > N\),无法执行翻转操作,输出 \(-1\)
- 执行翻转操作:
- 操作次数
ans++ - 更新差分数组:
diff[i] = (diff[i] + 1) % 2(在位置 \(i\) 开始翻转) - 更新差分数组:
diff[i+K] = (diff[i+K] - 1 + 2) % 2(在位置 \(i+K\) 结束翻转,处理负数)
- 操作次数
- 若
- 计算当前累积影响:
- 输出最少操作次数 \(ans\)
- 初始化差分数组:
-
时间/空间复杂度:
- 时间复杂度:\(O(N)\),遍历数组一次,每次操作 \(O(1)\)
- 空间复杂度:\(O(N)\),差分数组空间
-
差分数组与贪心的核心思想:
- 区间操作降维:差分数组将区间 \([l, r]\) 的翻转操作转化为
diff[l]++和diff[r+1]--,实现 \(O(1)\) 区间更新 - 贪心最优性:从左到右贪心翻转是最优的,因为每个位置一旦被处理就不会再被访问,且必须翻转时没有其他选择
- 前缀和还原:通过差分数组的前缀和(模 \(2\))快速计算每个位置的累积翻转状态
- 可行性判断:若剩余长度不足 \(K\) 且仍有灭的灯泡,则无解
- 适用于区间翻转、区间更新、贪心决策类问题
- 区间操作降维:差分数组将区间 \([l, r]\) 的翻转操作转化为
【解题思路】

【算法标签】
差分
【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
int n, k, ans, cur; // n: 数组长度,k: 翻转长度,ans: 操作次数,cur: 当前值(未使用)
int a[N], diff[N]; // a: 原始数组,diff: 差分数组
int main()
{
cin >> n >> k; // 读入数组长度和翻转长度
for (int i = 1; i <= n; i++)
{
cin >> a[i]; // 读入原始数组
}
for (int i = 1; i <= n; i++) // 遍历每个位置
{
// 计算差分数组的前缀和,得到当前位置的累积影响
diff[i] = (diff[i - 1] + diff[i]) % 2; // 对2取模,相当于异或操作
// 当前位置的状态 = 原始状态 ^ 累积影响
int state = a[i] ^ diff[i]; // ^ 是异或运算
if (state == 1) // 如果状态为1,需要翻转
{
if (i + k - 1 <= n) // 检查是否可以在位置i执行翻转操作
{
ans++; // 操作次数加1
// 更新差分数组:在位置i处+1,在位置i+k处-1
diff[i] = (diff[i] + 1) % 2; // 对2取模
diff[i + k] = (diff[i + k] - 1 + 2) % 2; // 处理负数,对2取模
}
else // 无法执行翻转操作
{
cout << -1 << endl; // 输出-1表示无解
return 0;
}
}
}
cout << ans << endl; // 输出最少操作次数
return 0;
}
【运行结果】
5 3
0 1 1 1 0
1
浙公网安备 33010602011771号