题目大意:在一串字符串中某个区间查询wbw的数目,更新某个位置的字符
思路:线段树,每个枝结点记录以这个点为中心的字符是不是wbw,所以每次某个位置更新的时候,左右两个位置均要更新
而且查询的时候某个区间的wbw的个数,位于边界的字符的值不能算在内
用树状数组编程难度会降低
//561MS 3400K 3373 B
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define RR(x) (x<<1|1)
#define LL(x) (x<<1)
const int M =50000+5000;
int n,m;
char str[M];
int rts[M];//每个字符位置对应线段树根结点的位置
struct node
{
int l,r;
int sum;
int mid()
{
return (l+r)>>1;
}
};
inline bool ok(int pos)
{
return (str[pos]=='b'&&str[pos-1]=='w'&&str[pos+1]=='w');
}
struct Segtree
{
node tree[M<<2];
void up(int rt)
{
tree[rt].sum=tree[LL(rt)].sum+tree[RR(rt)].sum;
}
void build(int l,int r,int rt)
{
tree[rt].l = l;
tree[rt].r = r;
if(l==r)
{
rts[l]=rt;
if(l==0||l==n-1) tree[rt].sum=0;
else tree[rt].sum = ok(l);
return ;
}
int mid=tree[rt].mid();
build(l,mid,LL(rt));
build(mid+1,r,RR(rt));
up(rt);
}
void update(int pos,char ch,int rt)
{
if(tree[rt].l==tree[rt].r)
{
str[pos]=ch;
if(pos==0||pos==n-1) tree[rt].sum=0;
else tree[rt].sum= ok(pos);
return ;
}
int mid=tree[rt].mid();
if(pos<=mid) update(pos,ch,LL(rt));
else update(pos,ch,RR(rt));
up(rt);
}
int query(int L,int R,int rt)
{
if(L<=tree[rt].l&&tree[rt].r<=R)
{
int tmp=0;
if(L==tree[rt].l&&tree[rts[L]].sum) tmp++;
if(R==tree[rt].r&&tree[rts[R]].sum) tmp++;
if(L==R) tmp=tree[ rts[R] ].sum ;
return tree[rt].sum-tmp;
}
int sum=0;
int mid=tree[rt].mid();
if(L<=mid) sum+=query(L,R,LL(rt));
if(R>mid) sum+=query(L,R,RR(rt));
return sum;
}
}seg;
int main()
{
int T;
scanf("%d",&T);
for(int cas=1;cas<=T;cas++)
{
printf("Case %d:\n",cas);
scanf("%d%d",&n,&m);
scanf("%s",str);
seg.build(0,n-1,1);
while(m--)
{
int op;
scanf("%d",&op);
if(op==0)
{
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",seg.query(l,r,1));
}
else
{
int p;
char ch;
scanf("%d %c",&p,&ch);
seg.update(p,ch,1);
if(p-1>0) seg.update(p-1,str[p-1],1);
if(p+1<n-1) seg.update(p+1,str[p+1],1);
}
}
}
return 0;
}
树状数组:
//421MS 1928K 1865 B C++
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M= 50000+5000;
char str[M];
int sum[M];
int n,m;
bool book[M];
inline int lowbit(int x)
{
return x&-x;
}
void update(int p,int val)
{
for(int i=p;i<M;i+=lowbit(i))
{
sum[i]+=val;
}
}
int getsum(int rt)
{
int ans=0;
for(int i=rt;i>0;i-=lowbit(i))
ans+=sum[i];
return ans;
}
inline bool ok(int p)
{
return (str[p-1]=='w'&&str[p]=='b'&&str[p+1]=='w');
}
void up(int p)
{
if(p<=1||p>=n) return ;
if(book[p]<ok(p))
{
book[p]=ok(p);
update(p,1);
}
else if(book[p]>ok(p))
{
book[p]=ok(p);
update(p,-1);
}
}
int main()
{
int T;
scanf("%d",&T);
for(int cas=1;cas<=T;cas++)
{
printf("Case %d:\n",cas);
scanf("%d%d",&n,&m);
scanf("%s",str+1);
book[1]=book[n]=0;
memset(sum,0,sizeof(sum));
for(int i=2;i<n;i++)
{
book[i]=ok(i);
if(book[i])update(i,book[i]);
}
while(m--)
{
int op;
scanf("%d",&op);
if(op==0)
{
int l,r;
scanf("%d%d",&l,&r);
l++,r++;
int ans=getsum(r)-getsum(l-1);
int tmp=book[l]+book[r];
if(l==r) tmp=book[l];
ans-=tmp;
printf("%d\n",ans);
}
else
{
int p;
char ch;
scanf("%d %c",&p,&ch);
p++;
str[p]=ch;
up(p);
up(p-1);
up(p+1);
}
}
}
return 0;
}