题意:
给出一个只包含w和b的字符串,要求支持一下两种操作:1,统计区间[a,b]中wbw的数量。2,修改a[p]的值为v。
分析:
线段树,sum[o]为结点o的wbw的数量。
在建树时,对与o结点的sum[o]=sum[2*o]+sum[2*o+1];如果两个结点连接处有wbw则将sum[o]++;更新的过程类似于建树的过程。
在查询[ql,qr]区间的wbw数量时,当两个区间合并时若连接处有wbw则_sum++;注意这里和建树和更新时候的区别。
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
const int maxn=50000+100;
int n,m,T;
int num[4*maxn];
char s[maxn];
void build(int o,int L,int R){
int M=L+(R-L)/2;
if(L==R){
num[o]=0;
return ;
}
build(2*o,L,M);
build(2*o+1,M+1,R);
num[o]=num[2*o]+num[2*o+1];
if(R-L>1){
if(s[M]=='b'&&s[M-1]=='w'&&s[M+1]=='w'&&M-L>=1)
num[o]++;
if(s[M]=='w'&&s[M+2]=='w'&&s[M+1]=='b'&&R-M>=2)
num[o]++;
}
}
int p;//A[p]=v
char v;
void update(int o,int L,int R){
int M=L+(R-L)/2;
if(L==R){
s[L]=v;
num[o]=0;
return ;
}
if(p<=M)update(2*o,L,M);
if(p>M)update(2*o+1,M+1,R);
num[o]=num[2*o]+num[2*o+1];
if(R-L>1){
if(s[M]=='b'&&s[M-1]=='w'&&s[M+1]=='w'&&M-L>=1)
num[o]++;
if(s[M]=='w'&&s[M+2]=='w'&&s[M+1]=='b'&&R-M>=2)
num[o]++;
}
}
int ql,qr,_sum;
void query(int o,int L,int R){
if(ql<=L&&qr>=R){
_sum+=num[o];
return;
}
int M=L+(R-L)/2;
if(ql<=M)query(2*o,L,M);
if(qr>M)query(2*o+1,M+1,R);
if(ql<=M&&qr>M){
if(R-L>1){
if(s[M]=='b'&&s[M-1]=='w'&&s[M+1]=='w'&&M-ql>=1&&M-L>=1)//注意这里
_sum++;
if(s[M]=='w'&&s[M+2]=='w'&&s[M+1]=='b'&&qr-M>=2&&R-M>=2)
_sum++;
}
}
}
void tra(int o,int L,int R){
cout<<L<<"->"<<R<<" "<<num[o]<<endl;
if(L==R)
return ;
int M=L+(R-L)/2;
tra(2*o,L,M);
tra(2*o+1,M+1,R);
}
int main(){
scanf("%d",&T);
for(int k=1;k<=T;k++){
cout<<"Case "<<k<<":"<<endl;
scanf("%d%d",&n,&m);
scanf("%s",s);
build(1,0,n-1);
//tra(1,0,n-1);
int c;
for(int i=1;i<=m;i++){
scanf("%d",&c);
if(c==0){
scanf("%d%d",&ql,&qr);
_sum=0;
query(1,0,n-1);
cout<<_sum<<endl;
}
if(c==1){
scanf("%d %c",&p,&v);
update(1,0,n-1);
//tra(1,0,n-1);
}
}
}
return 0;
}
--------------------------------------------------------------------------------------我是分割线--------------------------------------------------------------------------------------------------------------------------------
刚刚去看了看大佬们的写法,发现自己写的太渣了。
对于wbw,只需统计符合wbw形式的b的数量就可以,先进行预处理,若s[i]=b,s[i-1]=s[i+1]=w;则a[i]=1,否则a[i]=0;那么对于查询[ql,qr]时,只需知道区间[ql,qr]内a[i]的区间和即可。只要这样预处理,题目便变成了最基本的点修改线段树