题面挺美的
题意:给出一个字符串,两种操作1.询问区间[l,r]内wbw有多少个(可重叠)2.将位置x的字符改为c
题解:分块和线段树都可以搞,分块很好解释,只需要单独处理边界问题。线段树区间合并需要将每次询问的区间拿出来单独处理一次。
分块:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#pragma comment(linker, "/STACK:1024000000,1024000000");
using namespace std;
#define INF 0x3f3f3f3f
#define maxn 50005
int n,m;
int num,block,l[maxn],r[maxn],belong[maxn];
char s[maxn];
int ans[maxn];
int solve(int x,int y)
{
int sum=0;
for(int i=x;i<=y-2;i++)
{
if(s[i]=='w'&&s[i+1]=='b'&&s[i+2]=='w') sum++;
}
return sum;
}
void init()
{
block=sqrt(n);
num=n/block;
if(n%block) num++;
for(int i=1;i<=n;i++)
{
belong[i]=(i-1)/block+1;
}
for(int i=1;i<=num;i++)
{
l[i]=(i-1)*block+1;
r[i]=i*block;
}
r[num]=n;
for(int i=1;i<=num;i++)
{
ans[i]=solve(l[i],r[i]);
}
}
void update(int x,char c)
{
s[x]=c;
ans[belong[x]]=solve(l[belong[x]],r[belong[x]]);
}
int query(int x,int y)
{
if(belong[x]==belong[y])
{
return solve(x,y);
}
int sum=0;
sum+=solve(x,r[belong[x]]);
for(int i=belong[x]+1;i<=belong[y];i++)
{
if(i!=belong[y]) sum+=ans[i];
sum+=solve(max(x,l[i]-2),min(y,l[i]+1));
}
sum+=solve(l[belong[y]],y);
return sum;
}
int main()
{
int ca=1;
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
scanf("%s",s+1);
init();
printf("Case %d:\n",ca++);
while(m--)
{
int op;
scanf("%d",&op);
if(op==0)
{
int a,b;
scanf("%d%d",&a,&b);
a++,b++;
printf("%d\n",query(a,b));
}
else
{
int a;
char c[3];
scanf("%d%s",&a,c);
a++;
update(a,c[0]);
}
}
}
return 0;
}
线段树:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#pragma comment(linker, "/STACK:1024000000,1024000000");
using namespace std;
#define INF 0x3f3f3f3f
char s[50005];
int sum[200005];
int Merge(int l,int r)
{
int mid=l+r>>1;
int sum=0;
for(int i=max(mid-1,l);i<=mid;i++)
{
if(i+2>r) break;
if(s[i]=='w'&&s[i+1]=='b'&&s[i+2]=='w') sum++;
}
return sum;
}
void init(int l,int r,int k)
{
if(l==r)
{
sum[k]=0;
return ;
}
int mid=l+r>>1;
init(l,mid,k<<1);
init(mid+1,r,k<<1|1);
sum[k]=sum[k<<1]+sum[k<<1|1]+Merge(l,r);
}
void update(char c,int d,int l,int r,int k)
{
if(l==d&&r==d)
{
s[l]=c;
return ;
}
int mid=l+r>>1;
if(d<=mid) update(c,d,l,mid,k<<1);
else update(c,d,mid+1,r,k<<1|1);
sum[k]=sum[k<<1]+sum[k<<1|1]+Merge(l,r);
}
vectorint ,int> >vec;
int query(int s,int t,int l,int r,int k)
{
if(s==l&&r==t)
{
vec.push_back(pair<int ,int>(s,t));
return sum[k];
}
int mid=l+r>>1;
if(t<=mid) return query(s,t,l,mid,k<<1);
else if(s>mid) return query(s,t,mid+1,r,k<<1|1);
else return query(s,mid,l,mid,k<<1)+query(mid+1,t,mid+1,r,k<<1|1);
}
int main()
{
int T,ca=1;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
scanf("%s",s+1);
s[0]='#';
s[n+1]='#';
s[n+2]='#';
init(1,n,1);
printf("Case %d:\n",ca++);
while(m--)
{
int op;
scanf("%d",&op);
if(op==0)
{
int a,b;
scanf("%d%d",&a,&b);
a++;
b++;
vec.clear();
int ans=query(a,b,1,n,1);
for(int i=0;i1;i++)
{
int x=vec[i].second;
for(int j=max(vec[i].first,x-1);j<=x;j++)
{
if(j+2>b) break;
if(s[j]=='w'&&s[j+1]=='b'&&s[j+2]=='w') ans++;
}
}
printf("%d\n",ans);
}
else
{
int a;
char str[3];
scanf("%d%s",&a,str);
a++;
update(str[0],a,1,n,1);
}
}
}
return 0;
}