题意即为求wbw在所给范围的字符串中出现的次数。
线段树求解;
线段树中每个节点存的是以该节点结尾的三个字符,如果是wbw,该节点就为1,否则为0,需要注意的是更新的时候,如果该节点不是wbw,原本为1的应该改为0;
代码如下:
#include<stdio.h>
#include<string.h>
#define maxn 50002
struct tt
{
int l,r;
int sum;
};
tt tree[maxn*4];
char str[maxn];
int ans;
void pushup(int rt)
{
tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
}
void buildtree(int l,int r,int rt)
{
tree[rt].l=l;
tree[rt].r=r;
tree[rt].sum=0;
if(l==r)
{
if(r<=2) return ;
if(r>2)
if(str[r]=='w'&&str[r-1]=='b'&&str[r-2]=='w')
tree[rt].sum=1;
return ;
}
int mid=(l+r)/2;
buildtree(l,mid,rt<<1);
buildtree(mid+1,r,rt<<1|1);
pushup(rt);
}
void query(int l,int r,int rt,int L,int R)
{
if(l<=L&&R<=r)
{
ans+=tree[rt].sum;
return ;
}
int mid=(R+L)/2;
if(r<=mid)
query(l,r,rt<<1,L,mid);
else if(l>mid)
query(l,r,rt<<1|1,mid+1,R);
else
{
query(l,r,rt<<1,L,mid);
query(l,r,rt<<1|1,mid+1,R);
}
}
void update(int r,int L,int R,int rt)
{
if(L==R)
{
if(str[R]=='w'&&str[R-1]=='b'&&str[R-2]=='w')
tree[rt].sum=1;
else tree[rt].sum=0;
return ;
}
int mid=(L+R)/2;
if(r<=mid) update(r,L,mid,rt<<1);
else update(r,mid+1,R,rt<<1|1);
pushup(rt);
}
int main()
{
int ncase,n,m,cc=1;
scanf("%d",&ncase);
while(ncase--)
{
printf("Case %d:\n",cc++);
scanf("%d%d",&n,&m);
getchar();
scanf("%s",str+1);
buildtree(1,n,1);
int x,y,h;
char ss;
while(m--)
{
scanf("%d",&x);
if(x==0)
{
scanf("%d%d",&y,&h);
if(h-y<2){printf("0\n");continue;}
ans=0;
query(y+2+1,h+1,1,1,n);
printf("%d\n",ans);
}
else
{
scanf("%d %c",&y,&ss);
y++;
str[y]=ss;
if(y>=3) update(y,1,n,1);
if(y+1<=n) update(y+1,1,n,1);
if(y+2<=n) update(y+2,1,n,1);
}
}
}
return 0;
}