标签:
题目大意:在一串字符串中某个区间查询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;
}
标签:
原文地址:http://blog.csdn.net/kalilili/article/details/44171539