题意:长度为n的字符串,只有'w'和'b'两种字符,有m个操作。要么查询某个区间内有多少个连续的"wbw",要么修改某个位置的字符,对每次查询输出结果。
思路:线段树(单点修改)。开始没注意看题,写成区间修改了,所以代码也是从那个模式改过来的。然后只要清楚节点保存的内容就好做了,每个节点表示一个区间,保存区间内"wbw"的个数、最左边两个字符和最右边两个字符,就可以进行合并了,具体方法见代码。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
#define maxn 50010
char str[maxn];
struct node{
int l,r;
int val; //有几个wbw
char l1,l2; //最左边,次左边字符
char r1,r2; //最右边,次右边字符
};
node tree[maxn<<2];
void push_up(node& p,node& lch, node& rch){
p.l=lch.l;p.r=rch.r;
if(p.l+1==p.r){
p.l1=p.r2=lch.l1;
p.l2=p.r1=rch.r1;
p.val=0;
}else if(p.l+2==p.r){
char mid=max( lch.l2,rch.r2 );
p.l1=lch.l1;
p.r1=rch.r1;
p.l2=p.r2=mid;
if(p.l1=='w'&&mid=='b'&&p.r1=='w')p.val=1;
else p.val=0;
}else{
p.l1=lch.l1;
p.l2=lch.l2;
p.r1=rch.r1;
p.r2=rch.r2;
p.val=lch.val+rch.val;
if(lch.r2=='w'&&lch.r1=='b'&&rch.l1=='w')p.val++;
if(lch.r1=='w'&&rch.l1=='b'&&rch.l2=='w')p.val++;
}
}
void build_tree(int n,int l,int r){
tree[n].l=l; tree[n].r=r;
tree[n].val=0;
if(l==r){
tree[n].l1=tree[n].r1=str[l];
tree[n].l2=tree[n].r2=0; //这里忘记初始化WA了几发
return;
}
int mid=(l+r)>>1;
build_tree(n<<1,l,mid);
build_tree((n<<1)|1,mid+1,r);
push_up(tree[n],tree[n<<1],tree[(n<<1)|1]);
}
void update(int n,int l,int r,char ch){
if(tree[n].l==tree[n].r){
tree[n].l1=tree[n].r1=ch;
tree[n].val=0;
return;
}
int mid=(tree[n].l+tree[n].r)>>1;
if(r<=mid){
update(n<<1,l,r,ch);
}else{
if(l>mid){
update((n<<1)|1,l,r,ch);
}else{
update(n<<1,l,mid,ch);
update((n<<1)|1,mid+1,r,ch);
}
}
push_up(tree[n],tree[n<<1],tree[(n<<1)|1]);
}
node query(int n,int l,int r){
if(tree[n].l==l&&tree[n].r==r){
return tree[n];
}
int mid=(tree[n].l+tree[n].r)>>1;
if(r<=mid){
return query(n<<1,l,r);
}else{
if(l>mid){
return query((n<<1)|1,l,r);
}else{
node re;
node nl=query(n<<1,l,mid);
node nr=query((n<<1)|1,mid+1,r);
push_up(re,nl,nr);
return re;
}
}
}
int main(){
int t;
cin>>t;
int cas=0;
while(t--){
cas++;
printf("Case %d:\n",cas);
int n,m;
cin>>n>>m;
scanf("%s",str+1);
build_tree(1,1,n);
for(int i=1;i<=m;i++){
int op;
scanf("%d",&op);
if(op){
int a;
char b[4];
scanf("%d%s",&a,b);
a++;
update(1,a,a,b[0]);
}else{
int a,b;
scanf("%d%d",&a,&b);
a++;b++;
node ans=query(1,a,b);
printf("%d\n",ans.val);
}
}
}
return 0;
}