只要明白下区间如何更新上区间就可以了,左区间和右区间中只能、可能是右区间右边界中有'w',然后右区间左边界有'b''w',或者是右区间左边界有'w',左区间右边界有'w''b',满足这个情况下面,才可能上面的区间wbw组合增多。所以只要明白这个就ok了。。。
View Code
1 #include<iostream> 2 #include<stdio.h> 3 using namespace std; 4 const int N = 50005; 5 int cover[N<<2]; 6 char temp[N]; 7 void PushUp(int t,int l,int r,int m) 8 { 9 cover[t]=cover[t<<1]+cover[t<<1|1]; 10 if(l<=m&&m+2<=r) 11 if(temp[m]=='w'&&temp[m+1]=='b'&&temp[m+2]=='w') 12 cover[t]++; 13 if(l<=m-1&&m+1<=r) 14 if(temp[m-1]=='w'&&temp[m]=='b'&&temp[m+1]=='w') 15 cover[t]++; 16 } 17 void build(int t,int l,int r) 18 { 19 cover[t]=0; 20 if(l==r)return ; 21 int m=(l+r)>>1; 22 build(t<<1,l,m); 23 build(t<<1|1,m+1,r); 24 PushUp(t,l,r,m); 25 } 26 void update(int t,int l,int r,int p) 27 { 28 if(l==r)return ; 29 int m=(r+l)>>1; 30 if(p<=m)update(t<<1,l,m,p); 31 else update(t<<1|1,m+1,r,p); 32 PushUp(t,l,r,m); 33 } 34 int query(int t,int l,int r,int L,int R) 35 { 36 if(L<=l&&r<=R)return cover[t]; 37 int m=(r+l)>>1; 38 int ans=0; 39 if(L<=m)ans+=query(t<<1,l,m,L,R); 40 if(R>m)ans+=query(t<<1|1,m+1,r,L,R); 41 if(l<=m&&L<=m&&r>=m+2&&R>=m+2) 42 if(temp[m]=='w'&&temp[m+1]=='b'&&temp[m+2]=='w') 43 ans++; 44 if(l<=m-1&&L<=m-1&&r>=m+1&&R>=m+1) 45 if(temp[m-1]=='w'&&temp[m]=='b'&&temp[m+1]=='w') 46 ans++; 47 return ans; 48 } 49 int main() 50 { 51 int t,n,m; 52 int ord,a,b,T=0; 53 char op; 54 scanf("%d",&t); 55 while(t--) 56 { 57 scanf("%d%d",&n,&m); 58 n--; 59 scanf("%s",temp); 60 build(1,0,n); 61 printf("Case %d:\n",++T); 62 for(int i=0;i<m;i++) 63 { 64 scanf("%d",&ord); 65 if(ord) 66 { 67 scanf("%d %c",&a,&op); 68 temp[a]=op; 69 update(1,0,n,a); 70 } 71 else 72 { 73 scanf("%d%d",&a,&b); 74 printf("%d\n",query(1,0,n,a,b)); 75 } 76 } 77 } 78 return 0; 79 }