dousha的篮球时间

众所周知实验室的dousha(也就是dyx)学姐不仅打码强,篮球也打的猛(身体是革命的本钱啊)。
某一天doush学姐又带着实验室里的大三学长们去打球了,dousha学姐连续投了n个球,被学长们用一个长度为n的01字符串s(只包含0或者1的字符串)记录了下来。
s[i]=1代表dousha学姐的第i个投球进了,s[i]=0代表dousha学姐的第i个投球没进。
现在dousha学姐想知道她在这n次投篮的过程中,有多少个连续进球的时期,直观得说就是这个01字符串中有几个连续的由1组成的区间(111算1个区间而不是6个)。
但是由于记录数据的机器坏掉了,它会在每一秒变化这个01字符串的某一个位置上的数。原本是0就会变成1,原本是1就会变成0。
这就能难倒万能的dousha学姐么,她非常迅速得计算出了初始以及q次改变中每次改变后的01字符串中,连续的由1组成的区间个数,机智的小可爱们能做到么?
输入描述:
第一行包含两个正数n和q,分别代表字符串s的长度以及改变操作的次数。(1≤n,q≤1×106)第二行包含一个长度为n的字符串s,代表初始记录下来的01字符串。第三行包含q个整数ai,代表第i次操作分别改变了第几次操作的进球状况。(1≤ai≤n)
输出描述:
输出q+1行,每行一个整数,分别代表初始字符串以及q次改变操作每次操作后的字符串s中,连续的由1组成的区间个数。

思路:

直接判断改变位置左右可能的所有的情况,当时脑子比较浆糊,其实有些情况可以合并的

#include<stdio.h>
#include<iostream>
#include<vector>
#include<math.h>
#include<bits/stdc++.h>
#define ll long long
using namespace std;
char s[1000005];
int main(){
	int n,q;
	scanf("%d%d",&n,&q);
	getchar();
	for(int i=1;i<=n;i++)
	scanf("%c",&s[i]);
	int num=0,flag=0;
	for(int i=1;i<=n;i++){
		if(s[i]=='1'&&flag==0){
			flag=1;
			num++;
		}
		else if(flag==1&&s[i]=='0'){
			flag=0;
		}
	} 
	//算出开始的连续区间个数
	cout<<num<<endl;
	for(int i=1;i<=q;i++){
		int oper;
		scanf("%d",&oper);
		if(n==1){//特判n=1的情况
			if(s[1]=='0')s[1]='1',printf("1\n");
			else s[1]='0',printf("0\n");
			continue;
		}
		if(oper>1&&oper<n){//改变的点在中间
		if(s[oper]=='1'){
			if(s[oper+1]=='1'){//1 1 1
				if(s[oper-1]=='1'){
					num++;
				}
			}
			else if(s[oper+1]=='0'){ //0 1 0
				if(s[oper-1]=='0'){
					num--;
				}
			}
			s[oper]='0';
		}
		else if(s[oper]=='0'){
			if(s[oper+1]=='1'){//1 0 1
				if(s[oper-1]=='1'){
					num--;
				}
			}
			else if(s[oper+1]=='0'){// 0 0 0
				if(s[oper-1]=='0'){
					num++;
				}
			}
			s[oper]='1';
		}
	}
	else if(oper==1){//在开头
		if(s[oper]=='0'){
			if(s[oper+1]=='0')num++;//0 0
			s[oper]='1';
		}
		else{
			if(s[oper+1]=='0')num--;// 1 0
			s[oper]='0';
		}
	}
	else if(oper==n){//在末尾
		if(s[oper]=='0'){
			if(s[oper-1]=='0')num++;//0 0
			s[oper]='1';
		}
		else{
			if(s[oper-1]=='0')num--;//0 1
			s[oper]='0';
		}
	}
	//for(int i=1;i<=n;i++)cout<<s[i];
//	cout<<endl;
	printf("%d\n",num);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值