zoukankan      html  css  js  c++  java
  • CF242E XOR on Segment【题解】线段树按位维护

    题面:https://www.luogu.org/problem/CF242E

    因为XOR的lazy tag不可以叠加。

    所以就弄得比较麻烦。

    需要把每个数二进制拆分。

    也把lazy tag二进制拆分。

    0异或一个数还是那个数,1异或一个数就是取反。

    所以遇见tag的第i位为1的时候就用总数减去现在的这位为1的个数。

    然后所有都用线段树维护就行了。

    代码如下:

    #include<bits/stdc++.h>
    #define ll long long
    #define int long long
    using namespace std;
    const int maxn=100010;
    int n,a[maxn],f[maxn<<2][30],tg[maxn<<2];
    
    inline void pushup(int p){
        for(int i=0;i<21;i++)
            f[p][i]=f[(p<<1)][i]+f[(p<<1|1)][i];
        return;
    }
    void build(int p,int l,int r){
        if(l==r){
            int now=a[l];
            for(int i=0;i<21;i++)
                if((now>>i) & 1) f[p][i]++;
            return;
        }
        int mid=(l+r)>>1;
        build(p<<1,l,mid);build(p<<1|1,mid+1,r);
        pushup(p);
    }
    inline void pushdown(int p,int l,int r){
        if(!tg[p]) return;
        tg[(p<<1)]^=tg[p];tg[(p<<1|1)]^=tg[p];
        int mid=(l+r)>>1;
        for(int i=0;i<21;i++)
            if((tg[p]>>i)&1){
                f[(p<<1)][i]=mid-l+1-f[(p<<1)][i];
                f[(p<<1|1)][i]=r-mid-f[(p<<1|1)][i];
            }
        tg[p]=0;
        return;
    }
    inline ll ask(int p,int l,int r,int x,int y){
        if(x<=l && r<=y){
            ll ans=0;
            for(int i=0;i<21;i++)
                ans+=f[p][i]*(1<<i);
            return ans;
        }
        pushdown(p,l,r);
        ll ans=0;int mid=(l+r)>>1;
        if(x<=mid) ans+=ask(p<<1,l,mid,x,y);
        if(y>mid) ans+=ask(p<<1|1,mid+1,r,x,y);
        return ans;
    }
    inline void change(int p,int l,int r,int x,int y,int d){
        if(x<=l && r<=y){
            tg[p]^=d;
            for(int i=0;i<21;i++)
                if((d>>i)&1)
                    f[p][i]=r-l+1-f[p][i];
            return;
        }
        pushdown(p,l,r);
        int mid=(l+r)>>1;
        if(x<=mid) change(p<<1,l,mid,x,y,d);
        if(y>mid) change(p<<1|1,mid+1,r,x,y,d);
        pushup(p);
    }
    signed main()
    {
        scanf("%lld",&n);
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]);
        build(1,1,n);
        int q;scanf("%lld",&q);
        while(q--){
            int op;scanf("%lld",&op);
            if(op==1){
                int l,r;scanf("%lld%lld",&l,&r);
                printf("%lld
    ",ask(1,1,n,l,r));
            }else{
                int l,r,x;scanf("%lld%lld%lld",&l,&r,&x);
                change(1,1,n,l,r,x);
            }
        }
        return 0;
    }
  • 相关阅读:
    北航OO第三单元总结
    北航OO第二单元总结
    提问回顾和个人总结
    Unity 制作不规则形状button
    Unity 3D手游对不同分辨率屏幕的UI自适应
    软工结队作业
    CSDN app分析
    软工作业——求交点
    软工第一次作业
    软工热身作业
  • 原文地址:https://www.cnblogs.com/ChrisKKK/p/11537488.html
Copyright © 2011-2022 走看看