2017吉林省赛 C题 线段树

题意: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;
}

你可能感兴趣的:(线段树)