题意:
给你一个字符串,由’w’ 和 ‘b’ 组成,对该字符串有两种操作,
当输入为 0 a b 时,询问区间[a,b] 内有多少个串为 “wbw”;
当输入为 1 k ch 时,将下标为k的字符改为字符ch;
解析:
线段树单点更新的题目,用线段树来查询这个区间有多少个 “wbw”。
当更新的时候,就用连续更新当前点和后面两点,因为一次修改会修改后面两个位置的”wbw”的个数。
AC代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ls o*2
#define rs o*2+1
using namespace std;
const int N = 50005;
char str[N];
int sumv[N<<2];
inline void maintion(int o) {
sumv[o] = sumv[ls] + sumv[rs];
}
void build(int o, int L, int R) {
if(L == R) {
if(L < 2) sumv[o] = 0;
else if(str[L-2] == 'w' && str[L-1] == 'b' && str[L] == 'w')
sumv[o] = 1;
else sumv[o] = 0;
//printf("%d", sumv[o]);
return;
}
int M = (L+R)/2;
build(ls, L, M);
build(rs, M+1, R);
maintion(o);
}
int ql, qr;
char val;
int query(int o, int L, int R) {
if(ql <= L && R <= qr) {
return sumv[o];
}
int M = (L+R)/2;
int ret = 0;
if(ql <= M) ret += query(ls, L, M);
if(qr > M) ret += query(rs, M+1, R);
return ret;
}
void modify(int o, int L, int R) {
if(ql == L && ql == R) {
str[L] = val;
if(str[L-2] == 'w' && str[L-1] == 'b' && str[L] == 'w') {
sumv[o] = 1;
}else { sumv[o] = 0; }
return ;
}
int M = (L+R)/2;
if(ql <= M) modify(ls, L, M);
else modify(rs, M+1, R);
maintion(o);
}
int main() {
int T, n, q, type, cas = 1;
char buf[3];
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &q);
scanf("%s", str);
build(1, 0, n);
printf("Case %d:\n", cas++);
while(q--) {
scanf("%d", &type);
if(type == 0) {
scanf("%d%d", &ql, &qr);
if(abs(qr - ql) < 2) puts("0");
else {
ql += 2;
printf("%d\n", query(1, 0, n));
}
}else {
int k;
scanf("%d%s", &k, buf);
ql = k, val = buf[0];
modify(1, 0, n);
if(k+1 < n) {
ql = k+1, val = str[k+1];
modify(1, 0, n);
}
if(k+2 < n) {
ql = k+2, val = str[k+2];
modify(1, 0, n);
}
}
}
}
return 0;
}