洛谷 AT_abc411_c [ABC411C] Black Intervals 题解

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 1lrN):

  • 从左数第 l l l 到第 r r r 个格子均为黑色;
  • l = 1 l = 1 l=1,或者从左数第 ( l − 1 ) (l − 1) (l1) 个格子为白色;
  • 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,A3AQ,表示每一个询问的参数。

输出格式

输出 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 25 被涂黑。存在 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 125 被涂黑。存在 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 12 被涂黑。存在 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 1N,Q5×105
  • 1 ≤ A i ≤ N 1 \le A_i \le N 1AiN
  • 读入的所有数都是整数。

1. 读题

题意其实挺清楚的:一排有 N N N 个格子,初始时所有格子均为白色。现在给出 Q Q Q 次修改和查询,问你黑色格子的数量。
举个例子:
样例:

5 7
2 3 3 5 1 5 2
  1. 全部是白色:

黑色区域数量:0。

  1. 第二个颜色反转。

黑色区域数量:1。

  1. 第3个颜色反转。

黑色区域数量:1。

  1. 第3个颜色反转。

黑色区域数量:1。

  1. 第5个颜色反转。

黑色区域数量:2。

  1. 第1个颜色反转。


黑色区域数量:2。

  1. 第5个颜色反转。

黑色数量:1。

  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 1N,Q5×105),暴力(两层循环)肯定是过不了,我们可以考虑边读入变计算的方法,用布尔数组存下每一个格子的状态,然后进行判断。

3. 代码详解

  1. 变量定义
#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; //计数器,有多少个黑色的个子。
  1. 数据读入及判断
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;
}

以上就是全部题解了,再说几句废话
推荐一下我的其他题解


如果对你有帮助,点个赞再走吧!谢谢!有任何问题请指出。

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

—海燕—

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值