题意:10w的RGB序列,每次把区间设为一个字母 或者把序列中的R换成B G换成R B变成G 一种询问 问区间中 每个字母各多少个。简单的线段树区间打标记,要注意操作间的影响。
#include
using namespace std;
#define maxn 410000
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define getmid int mid=(l+r)>>1;
int sum[maxn][3],tag[maxn],cov[maxn];
int n,q;
char st[maxn];
int fuck(char x)
{
if(x=='R') return 0;
if(x=='G') return 1;
if(x=='B') return 2;
return 0;
}
void pushup(int rt)
{
for(int i=0;i<3;i++)
sum[rt][i]=sum[rt<<1][i]+sum[rt<<1|1][i];
}
void pushdown(int rt,int l,int r)
{
if(tag[rt]==-1&&cov[rt]==0) return;
getmid
int f=tag[rt];
if(tag[rt]!=-1)
{
memset(sum[rt<<1],0,sizeof(sum[rt<<1]));
memset(sum[rt<<1|1],0,sizeof(sum[rt<<1|1]));
sum[rt<<1][f]=mid-l+1;
sum[rt<<1|1][f]=r-mid;
cov[rt<<1]=0;cov[rt<<1|1]=0;
tag[rt<<1]=f;
tag[rt<<1|1]=f;
tag[rt]=-1;
}
if(cov[rt])
{
int tmp;
for(int i=1;i<=cov[rt];i++)
{
tmp=sum[rt<<1][2];
sum[rt<<1][2]=sum[rt<<1][1];
sum[rt<<1][1]=sum[rt<<1][0];
sum[rt<<1][0]=tmp;
tmp=sum[rt<<1|1][2];
sum[rt<<1|1][2]=sum[rt<<1|1][1];
sum[rt<<1|1][1]=sum[rt<<1|1][0];
sum[rt<<1|1][0]=tmp;
}
cov[rt<<1]+=cov[rt];
cov[rt<<1|1]+=cov[rt];
cov[rt<<1]%=3;
cov[rt<<1|1]%=3;
cov[rt]=0;
}
}
void build(int l,int r,int rt)
{
if(l==r)
{
memset(sum[rt],0,sizeof(sum[rt]));
sum[rt][fuck(st[l])]=1;
return;
}
getmid
build(lson);
build(rson);
pushup(rt);
}
void update(int l,int r,int rt,int x,int y,int f)
{
if(x<=l&&r<=y)
{
tag[rt]=f;
memset(sum[rt],0,sizeof(sum[rt]));
sum[rt][f]=(r-l+1);
cov[rt]=0;
return;
}
pushdown(rt,l,r);
getmid;
if(x<=mid) update(lson,x,y,f);
if(y>mid) update(rson,x,y,f);
pushup(rt);
}
void update2(int l,int r,int rt,int x,int y)
{
if(x<=l&&r<=y)
{
cov[rt]++;
cov[rt]%=3;
int tmp=sum[rt][2];
sum[rt][2]=sum[rt][1];
sum[rt][1]=sum[rt][0];
sum[rt][0]=tmp;
return;
}
pushdown(rt,l,r);
getmid;
if(x<=mid) update2(lson,x,y);
if(y>mid) update2(rson,x,y);
pushup(rt);
}
int query(int l,int r,int rt,int x,int y,int f)
{
if(x<=l&&r<=y)
{
return sum[rt][f];
}
pushdown(rt,l,r);
getmid;
int s1=0,s2=0;
if(x<=mid) s1=query(lson,x,y,f);
if(y>mid) s2=query(rson,x,y,f);
return s1+s2;
}
char op[10],op2[10];
int main()
{
freopen("data.txt","r",stdin);
freopen("out.txt","w",stdout);
int cas,a,b;
cin>>cas;
for(int ii=1;ii<=cas;ii++)
{
memset(tag,-1,sizeof(tag));
memset(cov,0,sizeof(cov));
printf("Case #%d:\n",ii);
cin>>n>>q;
scanf("%s",st+1);
build(1,n,1);
for(int i=1;i<=q;i++)
{
scanf("%s",op+1);
if(op[2]=='E')
{
scanf("%d%d%s",&a,&b,op2+1);
update(1,n,1,a,b,fuck(op2[1]));
}
if(op[2]=='W')
{
scanf("%d%d",&a,&b);
update2(1,n,1,a,b);
}
if(op[1]=='Q')
{
scanf("%d%d",&a,&b);
printf("%d ",query(1,n,1,a,b,0));
printf("%d ",query(1,n,1,a,b,1));
printf("%d\n",query(1,n,1,a,b,2));
}
}
}
return 0;
}