FZU/FOJ 2105 Problem 2105 Digits Count 成段更新

题意:对一串数字进行抑或某数,和某数,或某数,统计某区间和的操作。

做法:对每一位进行统计。看了大神的代码之后才发现自己犯了个很2 的错误

#include<cstdio>
#include<cstring>
#define left l,m,x<<1
#define right m+1,r,x<<1|1
#define LMT 1000003
#define LL int
int cov[4][LMT<<2],wei;
int cover[4][LMT<<2],ox[4][LMT<<2];
//二进制数要记得算进去前面的0!!!
//标记不要太复杂啊....
void init(void)
{
    memset(cov,-1,sizeof(cov));
    memset(cover,0,sizeof(cover));
}
void fox(int l,int r,int x)
{
    if(cover[wei][x]!=-1)
        cover[wei][x]^=1;
    else ox[wei][x]^=1;
    cov[wei][x]=r-l+1-cov[wei][x];
}
void cut(int l,int r,int x)
{
    //要更新了原先的状态肯定无法保持了。
    int m=(l+r)>>1;
    if(cover[wei][x]!=-1)
    {
        int m=(l+r)>>1;
        cover[wei][x<<1]=cover[wei][x<<1|1]=cover[wei][x];
        ox[wei][x<<1]=ox[wei][x<<1|1]=0;
        cov[wei][x<<1]=(m-l+1)*cover[wei][x<<1];
        cov[wei][x<<1|1]=(r-m)*cover[wei][x<<1|1];
        cover[wei][x]=-1;
    }
    if(ox[wei][x])
    {
        fox(left),fox(right);
        ox[wei][x]=0;
    }
}
void update(char op,int L,int R,int l,int r,int x)
{
    if(L<=l&&r<=R)
    {
        if(op==1)
        {
            cov[wei][x]=r-l+1;
            cover[wei][x]=1;
            ox[wei][x]=0;
        }
        if(op==0)ox[wei][x]=cov[wei][x]=cover[wei][x]=0;//这里...
        if(op==2)fox(l,r,x);
            return;
    }
    cut(l,r,x);
    int m=(l+r)>>1;
    if(L<=m)update(op,L,R,left);
    if(R>m)update(op,L,R,right);
    cov[wei][x]=cov[wei][x<<1]+cov[wei][x<<1|1];
}
int sum(int L,int R,int l,int r,int x)
{
    if(L<=l&&r<=R)return cov[wei][x];
    cut(l,r,x);
    int m=(l+r)>>1,res=0;
    if(L<=m)res+=sum(L,R,left);
    if(R>m)res+=sum(L,R,right);
    return res;
}
int main(void)
{
    int T;
    scanf("%d",&T);
    char ord[5];
    while(T--)
    {
        init();
        int n,m,x,l,r;
        LL res;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            wei=0;
            for(int j=0;j<4;j++)//这里
            {
                if(x&(1<<j))update(1,i,i,1,n,1);
                else update(0,i,i,1,n,1);
                wei++;
            }
        }
        while(m--)
        {
            scanf("%s",ord);
            if(!strcmp(ord,"SUM"))
            {
                scanf("%d%d",&l,&r);
                l++;r++;res=0;
                for(wei=0;wei<4;wei++)res+=(1<<wei)*sum(l,r,1,n,1);
                printf("%d\n",res);
            }
            else
            {
                scanf("%d%d%d",&x,&l,&r);
                l++;r++;
            wei=0;
            for(int i=0;i<4;i++)
            {
                if(!strcmp(ord,"OR")&&(x&(1<<i)))update(1,l,r,1,n,1);
                if(!strcmp(ord,"XOR")&&(x&(1<<i)))update(2,l,r,1,n,1);
                if(!strcmp(ord,"AND")&&(~x&(1<<i)))update(0,l,r,1,n,1);
                wei++;
            }
            }
        }
    }
    return 0;
}


你可能感兴趣的:(FZU/FOJ 2105 Problem 2105 Digits Count 成段更新)