题目有两个操作:
1. 查询一段区间内的wbw的个数
2. 修改某一个位置的字母
我们用树状数组记录sum[i] 表示以i之前出线的wbw的个数
当查询a,b区间时sum[b] - sum[a+1]就是a,b间wbw的个数
当更新某个点时,只需判定改变这个字母所带来的wbw个数的变化,并更新到树状数组中即可
#include <iostream>
#include <cstdio>
#include <string>
#include <memory.h>
using namespace std;
const int M = 50005;
char ch[M];
int sum[M];
int n,m;
void INIT();
void sol();
void change(int k,int d);
int SUM(int k);
bool judge(int x);
int lowbit(int k);
int main()
{
int t,cas = 1;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
scanf("%s",&ch);
INIT();
printf("Case %d:\n",cas++);
sol();
}
}
void INIT()
{
memset(sum,0,sizeof(sum));
for(int i = 2;i < n;i++)
{
if(ch[i-2] == 'w' && ch[i-1] == 'b' && ch[i] == 'w')
change(i,1);
}
return;
}
void sol()
{
int a,b,c;
char d;
for(int i = 0;i < m;i++)
{
scanf("%d%",&a);
if(a == 0)
{
scanf("%d%d",&b,&c);
if(c - b <= 1)
printf("0\n");
else
printf("%d\n",SUM(c)- SUM(b + 1));
}
else if(a == 1)
{
scanf("%d",&b);
cin >> d;
if(d != ch[b])
{
if(judge(b))
change(b,-1);
if(judge(b+1))
change(b+1,-1);
if(judge(b+2))
change(b+2,-1);
ch[b] = d;
if(judge(b))
change(b,1);
if(judge(b+1))
change(b+1,1);
if(judge(b+2))
change(b+2,1);
}
}
}
}
bool judge(int x)
{
if(x < 2)return false;
if(ch[x-2] == 'w' && ch[x-1] == 'b' && ch[x] == 'w')
return true;
else return false;
}
int lowbit(int k){return k&(-k);}
void change(int k,int d)
{
while(k < M)
{
sum[k] += d;
k += lowbit(k);
}
return;
}
int SUM(int k)
{
int s = 0;
while(k > 0)
{
s += sum[k];
k-= lowbit(k);
}
return s;
}