Time Limit: 10000/4000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2396 Accepted Submission(s): 810
2 5 2 bwbwb 0 0 4 0 1 3 5 5 wbwbw 0 0 4 0 0 2 0 2 4 1 2 b 0 0 4
Case 1: 1 1 Case 2: 2 1 1 0
题意不在叙述,本题中可以将w和符合要求的转为1,否则为0 ,最后利用线段树求和,具体转化方式如下:
例:wbwbwbwwb 存入字符数组s[i] i = 9
同时建立整形数组a[j] j= 9;每个i和j相对应
每三个字符若满足条件,则将a[j]标记为1,否则为0,初始a全为0
则 wbwbwbwwb ---->>0 0 1 0 1 0 1 0 0
最后利用线段树求和即可
在改变某个结点的值时,要进行三次修改,代表三种情况,修改完后要更新线段树,具体代码如下:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define inf -0x3f3f3f3f
#define mem0(a) memset(a,0,sizeof(a))
const int num = 50000+10;
char s[num];
int a[num],sum[num<<2];
void Getsum(int cur){
sum[cur] = sum[cur<<1]+sum[cur<<1|1];
}
void build(int l,int r, int cur){
if( l == r ){
sum[cur] = a[l];
return ;
}
int mid = (l + r )>>1;
build(l,mid,cur<<1);
build(mid+1,r,cur<<1|1);
Getsum(cur);
}
void update(int k,int v,int l,int r,int cur){
if(l == r ){
sum[cur] = v;
return ;
}
int mid = ( l + r )>>1;
if(k <=mid ){
update(k,v,l,mid,cur<<1);
}
else {
update(k,v,mid+1,r,cur<<1|1);
}
Getsum(cur);
}
int query(int ql,int qr,int l,int r ,int cur){
if(ql <= l && qr >= r){
return sum[cur];
}
int mid = ( l + r )>>1;
int ans = 0 ;
if(ql <= mid) ans += query(ql,qr,l,mid,cur<<1);
if(qr > mid ) ans += query(ql,qr,mid+1,r,cur<<1|1);
return ans ;
}
int main()
{
int T,t =1 ;
scanf("%d",&T);
while(T--){
int n,m;
scanf("%d%d",&n,&m);
scanf("%s",s);
mem0(a);
for(int i = 2 ; i < n ; i++){
if(s[i]!='w') a[i]=0;
else if(s[i]=='w'&&s[i-1]=='b'&&s[i-2]=='w')
a[i]=1;
}
build(0,n,1);
printf("Case %d:\n",t++);
while(m--){
int aa,b,c;
char d;
scanf("%d",&aa);
if(aa == 0){
scanf("%d%d",&b,&c);
b+=2; //从b开始后第三个字母开始检测
if(b > c) //如果b,c长度小于3,直接输出0
printf("0\n");
else
printf("%d\n",query(b,c,0,n,1));
}
else if(aa == 1){
scanf("%d %c",&b,&d);
if(s[b]==d)
continue;//当改变值与原来一样,则continue,进行下次询问
s[b]=d; //否则值一定改变,下列假设都是在改变值的情况下建立的
//以b处为末尾的三个字符
if(b>=2&&s[b-2]=='w'&&s[b-1]=='b'&&s[b]=='w'){
// 改变之后符合要求
if(a[b]==0)//若改之前不符合要求,则更新
update(b,1,0,n,1);//更新线段树sum
a[b]=1;//原保存数组a也要更新
}
else if(b>=2&&a[b]==1){//如果原来符合要求,改过必不符合要求
update(b,0,0,n,1);//更新
a[b]=0;
}
//以b处为中间的三个字符
if(b>=1&&b<n-1&&s[b-1]=='w'&&s[b]=='b'&&s[b+1]=='w'){//同上
if(a[b+1]==0)
update(b+1,1,0,n,1);
a[b+1]=1;
}
else if(b < n-1 && b >= 1&&a[b+1]==1){
a[b+1]=0;
update(b+1,0,0,n,1);
}
//以b处为起始的三个字符
if(b+2<n&&s[b]=='w'&&s[b+1]=='b'&&s[b+2]=='w'){
if(a[b+2]==0)
update(b+2,1,0,n,1);
a[b+2]=1;
}
else if(b < n - 2 && a[b+2]==1){
a[b+2]=0;
update(b+2,0,0,n,1);
}
}
}
}
return 0;
}