题意:
给一个字符串,两种操作 0 a b 询问a,b之间有多少个wbw, 1 a c 就是把第a个改成c.
思路:
给一个字符串,两种操作 0 a b 询问a,b之间有多少个wbw, 1 a c 就是把第a个改成c.
思路:
这个题目我们可以用线段树的点更新来做,一开始写了个好长好长的线段树,pushup写了很长,每个节点7个变量,结果 "呵呵"。其实根本不用那么麻烦,我当时想的麻烦了,每个节点只有一个sum就行了,每个节点代表的是以当前这段的每个点为终点的wbw的个数,比如节点4,6那么当前的这个节点存的就是以4,5,6,为终点的wbw的个数(4,6最多三个),每次更新的时候改变当前的这个字母可能会影响三个权值改变,所以更新三次,具体看代码。
#include<stdio.h> #include<string.h> #define lson l ,mid ,t << 1 #define rson mid + 1 ,r ,t << 1 | 1 int sum[300000]; char num[55000]; void Pushup(int t) { sum[t] = sum[t<<1] + sum[t<<1|1]; } void BuidTree(int l ,int r ,int t) { sum[t] = 0; if(l == r) { if(l >= 3 && num[l] == 'w' && num[l-1] == 'b' && num[l-2] == 'w') sum[t] = 1; return ; } int mid = (l + r) >> 1; BuidTree(lson); BuidTree(rson); Pushup(t); } void Update(int l ,int r ,int t ,int a) { if(l == r) { if(num[l] == 'w' && num[l-1] == 'b' && num[l-2] == 'w') sum[t] = 1; else sum[t] = 0; return; } int mid = (l + r) >> 1; if(a <= mid) Update(lson ,a); else Update(rson ,a); Pushup(t); } int Query(int l ,int r ,int t ,int a ,int b) { if(a <= l && b >= r) return sum[t]; int mid = (l + r) >> 1; int Ans = 0; if(a <= mid) Ans = Query(lson ,a ,b); if(b > mid) Ans += Query(rson ,a ,b); return Ans; } int main () { int t ,n ,m ,a ,b ,c ,cas = 1; scanf("%d" ,&t); while(t--) { scanf("%d %d" ,&n ,&m); scanf("%s" ,num + 1); BuidTree(1 ,n ,1); printf("Case %d:\n" ,cas ++); while(m--) { scanf("%d" ,&a); if(!a) { scanf("%d %d" ,&b ,&c); b ++ ,c ++; if(c - b < 2) printf("0\n"); else printf("%d\n" ,Query(1 ,n ,1 ,b + 2 ,c)); } else { char str[5]; scanf("%d %s" ,&b ,str); num[++b] = str[0]; if(b >= 3) Update(1 ,n ,1 ,b); if(b + 1 >= 3 && b + 1 <= n) Update(1 ,n ,1 ,b + 1); if(b + 2 >= 3 && b + 2 <= n) Update(1 ,n ,1 ,b + 2); } } } return 0; }