AT_abc411_c [ABC411C] Black Intervals 题解
完整题目
AT_abc411_c [ABC411C] Black Intervals
题目描述
一排有 N N N 个格子,初始时所有格子均为白色。
你需要依次处理 Q Q Q 个查询。第 i i i 个查询会给出一个整数 A i A_i Ai,并执行以下操作:
翻转从左数第 A i A_i Ai 个格子的颜色。具体来说,如果该格子当前为白色,则将其涂黑;如果当前为黑色,则将其涂白。之后,统计当前所有连续的黑色格子区间的数量。
这里,连续的黑色格子区间是指满足以下所有条件的整数对 ( l , r ) (l, r) (l,r)( 1 ≤ l ≤ r ≤ N 1 \le l \le r \le N 1≤l≤r≤N):
- 从左数第 l l l 到第 r r r 个格子均为黑色;
- l = 1 l = 1 l=1,或者从左数第 ( l − 1 ) (l − 1) (l−1) 个格子为白色;
- r = N r = N r=N,或者从左数第 ( r + 1 ) (r + 1) (r+1) 个格子为白色。
输入格式
第一行为 N , Q N,Q N,Q,表示格子的个数和询问数。
接下来 Q Q Q 个数 A 1 , A 2 , A 3 … A Q A_1,A_2,A_3 \dots A_Q A1,A2,A3…AQ,表示每一个询问的参数。输出格式
输出 Q Q Q 行。对于第 i i i 行,为第 i i i 个询问的答案。
输入输出样例 #1
输入 #1
5 7 2 3 3 5 1 5 2
输出 #1
1 1 1 2 2 1 1
输入输出样例 #2
输入 #2
1 2 1 1
输出 #2
1 0
输入输出样例 #3
输入 #3
3 3 1 3 2
输出 #3
1 2 1
说明/提示
样例解释#1
以下将从左数第 i i i 个格子简称为格子 i i i。
每次查询后的状态如下:
第 1 1 1 次查询后:仅格子 2 2 2 被涂黑。存在 1 1 1 个连续黑色区间: ( l , r ) = ( 2 , 2 ) (l,r)=(2,2) (l,r)=(2,2)。
第 2 2 2 次查询后:格子 2 2 2、 3 3 3 被涂黑。存在 1 1 1 个连续黑色区间: ( l , r ) = ( 2 , 3 ) (l,r)=(2,3) (l,r)=(2,3)。
第 3 3 3 次查询后:仅格子 2 2 2 被涂黑。存在 1 1 1 个连续黑色区间: ( l , r ) = ( 2 , 2 ) (l,r)=(2,2) (l,r)=(2,2)。
第 4 4 4 次查询后:格子 2 、 5 2、5 2、5 被涂黑。存在 2 2 2 个连续黑色区间: ( l , r ) = ( 2 , 2 ) (l,r)=(2,2) (l,r)=(2,2) 和 ( l , r ) = ( 5 , 5 ) (l,r)=(5,5) (l,r)=(5,5)。
第 5 5 5 次查询后:格子 1 、 2 、 5 1、2、5 1、2、5 被涂黑。存在 2 2 2 个连续黑色区间: ( l , r ) = ( 1 , 2 ) (l,r)=(1,2) (l,r)=(1,2) 和 ( l , r ) = ( 5 , 5 ) (l,r)=(5,5) (l,r)=(5,5)。
第 6 6 6 次查询后:仅格子 1 、 2 1、2 1、2 被涂黑。存在 1 1 1 个连续黑色区间: ( l , r ) = ( 1 , 2 ) (l,r)=(1,2) (l,r)=(1,2)。
第 7 7 7 次查询后:仅格子 1 1 1 被涂黑。存在 1 1 1 个连续黑色区间: ( l , r ) = ( 1 , 1 ) (l,r)=(1,1) (l,r)=(1,1)。
因此,输出应为换行分隔的序列:
1 1 1
1 1 1
1 1 1
2 2 2
2 2 2
1 1 1
1 1 1数据范围
对于 100 % 100\% 100% 的数据保证:
- 1 ≤ N , Q ≤ 5 × 1 0 5 1 \le N,Q \le 5×10^5 1≤N,Q≤5×105;
- 1 ≤ A i ≤ N 1 \le A_i \le N 1≤Ai≤N;
- 读入的所有数都是整数。
1. 读题
题意其实挺清楚的:一排有
N
N
N 个格子,初始时所有格子均为白色。现在给出
Q
Q
Q 次修改和查询,问你黑色格子的数量。
举个例子:
样例:
5 7
2 3 3 5 1 5 2
- 全部是白色:

黑色区域数量:0。
- 第二个颜色反转。

黑色区域数量:1。
- 第3个颜色反转。

黑色区域数量:1。
- 第3个颜色反转。

黑色区域数量:1。
- 第5个颜色反转。

黑色区域数量:2。
- 第1个颜色反转。

黑色区域数量:2。
- 第5个颜色反转。

黑色数量:1。
- 第2个颜色反转。

黑色区域数量:1。
所以输出为
1
1
1
2
2
1
1
2. 解题思路
由于数据范围( 1 ≤ N , Q ≤ 5 × 1 0 5 1 \le N,Q \le 5×10^5 1≤N,Q≤5×105),暴力(两层循环)肯定是过不了,我们可以考虑边读入变计算的方法,用布尔数组存下每一个格子的状态,然后进行判断。
3. 代码详解
- 变量定义
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
bool col[N];//用于存储每一个格子的状态。
int n,q,a;//与题目中的意思相同
//n:n 个格子
//q:q 次查询、修改。
//a:每一次修改颜色的格子编号。
int cnt; //计数器,有多少个黑色的个子。
- 数据读入及判断
int main(){
cin>>n>>q;
while(q--){//有 n 次修改和查询。
cin>>a;
col[a]=!col[a];//黑变白,白变黑(取反)。
if(col[a]){//如果第 a 个是黑色
if(!col[a-1]&&!col[a+1]) cnt++; //如果这个黑色的个子左右两边都是白色格子,就相当于增加了一个黑色格子(不理解的话看一看上面的样例)
else if(col[a-1]&&col[a+1]) cnt--;//同理,如果这个黑色的个子左右两边都不是白色格子,就相当于减少了一个黑色格子
}
else{//如果第 a 个是白色
if(!col[a-1]&&!col[a+1]) cnt--; ////同理,如果这个白色的个子左右两边都是白色格子,就相当于减少了一个黑色格子
else if(col[a-1]&&col[a+1]) cnt++;//同理,如果这个白色的个子左右两边都不是白色格子,就相当于增加了一个黑色格子。
}
cout<<cnt<<'\n';
}
return 0;
}
4. AC代码
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
bool col[N];
int n,q,a;
int cnt;
int main(){
cin>>n>>q;
while(q--){
cin>>a;
col[a]=!col[a];
if(col[a]){
if(!col[a-1]&&!col[a+1]) cnt++;
else if(col[a-1]&&col[a+1]) cnt--;
}
else{
if(!col[a-1]&&!col[a+1]) cnt--;
else if(col[a-1]&&col[a+1]) cnt++;
}
cout<<cnt<<'\n';
}
return 0;
}
以上就是全部题解了,再说几句废话
推荐一下我的其他题解
如果对你有帮助,点个赞再走吧!谢谢!有任何问题请指出。





