题意:给定一个长度为5W的字符串,只包含字母w或者b,现在有1W个操作,0,l,r表示每次询问l,r区间内有多少连续的“wbw”; 1,i,c表示将第i个位置上的字符修改成字符c
分析: 树状数组的单点更新:求区间内有多少连续的"wbw",可以找出所有的“wbw”,用三个数组pre,mid,suc分别标记好,第i个位置的字符能否作为前缀w,中间的b或者后缀w,字符b所在的位置值更新+1,每次查询l,r,找到最接近l的前缀w,最接近r的后缀w,查询即可。
更新时,注意各种情况,三个数组pre,mid,suc该标记的标记,该消除的消除。
#include <iostream> #include <algorithm> #include <cmath> #include<functional> #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <vector> #include <set> #include <queue> #include <stack> #include <climits>//形如INT_MAX一类的 #define MAX 50555 #define INF 0x7FFFFFFF #define REP(i,s,t) for(int i=(s);i<=(t);++i) #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) #define mp(a,b) make_pair(a,b) #define L(x) x<<1 #define R(x) x<<1|1 # define eps 1e-5 using namespace std; int pre[MAX],mid[MAX],suc[MAX],c[MAX]; char str[MAX]; int n,m; void init() { memset(pre,0,sizeof(pre)); memset(suc,0,sizeof(suc)); memset(mid,0,sizeof(mid)); memset(c,0,sizeof(c)); } int lowbit(int x) { return x & (-x); } void update(int x,int va) { while(x <= n) { c[x] += va; x += lowbit(x); } } int query(int x) { int sum = 0; while(x > 0) { sum += c[x]; x -= lowbit(x); } return sum; } int main() { int T; int a,b,c; char op; cin >> T; int ca = 1; while(T--) { init(); scanf("%d%d",&n,&m); scanf("%s",str); for(int i=0; i<n-2; i++) { if(str[i] == 'w' && str[i+1] == 'b' && str[i+2] == 'w') { pre[i] = 1; mid[i+1] = 1; suc[i+2] = 1; update(i+2,1); } } printf("Case %d:\n",ca++); for(int i=0; i<m; i++) { scanf("%d",&a); if(a == 0) { scanf("%d%d",&b,&c); while(pre[b] == 0) { b ++; } while(suc[c] == 0) { c --; } if(c < b) printf("0\n"); else { printf("%d\n",query(c+1) - query(b)); } } else { scanf("%d %c",&b,&op); if(op == 'b') { if(str[b] == 'w') { str[b] = 'b'; if(pre[b] == 1) { pre[b] = 0; mid[b+1] = 0; suc[b+2] = 0; update(b+2,-1); } if(suc[b] == 1) { pre[b-2] = 0; mid[b-1] = 0; suc[b] = 0; update(b,-1); } if(str[b-1] == 'w' && str[b+1] == 'w') { pre[b-1] = 1; mid[b] = 1; suc[b+1] = 1; update(b+1,1); } } } else { if(str[b] == 'b') { str[b] = 'w'; if(mid[b] == 1) { pre[b-1] = 0; mid[b] = 0; suc[b+1] = 0; update(b+1,-1); } if(str[b+1] == 'b' && str[b+2] == 'w') { pre[b] = 1; mid[b+1] = 1; suc[b+2] = 1; update(b+2,1); } if(str[b-1] == 'b' && str[b-2] == 'w') { pre[b-2] = 1; mid[b-1] = 1; suc[b] = 1; update(b,1); } } } } } } return 0; }