• 关于区间异或的线段树


    题:https://codeforces.com/problemset/problem/242/E?csrf_token=e91633dfd98d038f51cc388731fe3f4d

    题意:俩个操作,操作1:(l,r,x),区间[l,r]的数全部异或上x。操作2:(l ,r)输出区间[l,r]和;

    分析:对数组a建线段树,对于线段树的每一个节点进行二进制拆位,每个位就统计有多少个1,更新操作对于涵盖区间的二进制位就等于其长度减去更新前的1的个数;

    #include<bits/stdc++.h>
    using namespace std;
    #define lson root<<1,l,midd
    #define rson root<<1|1,midd+1,r
    typedef long long ll;
    const int N=30;
    const int M=1e5+5;
    ll lz[M<<2][N],tr[M<<2][N],a[M];
    void up(int root){
        for(int i=0;i<=20;i++)
            tr[root][i]=tr[root<<1][i]+tr[root<<1|1][i];
    }
    void build(int root,int l,int r){
        if(l==r){
            int x=a[l];
            for(int i=0;i<=20;i++){
                if(x&(1<<i)){
                    tr[root][i]=1;
                }
            }
            return ;
        }
        int midd=(l+r)>>1;
        build(lson);
        build(rson);
        up(root);
    }
    void pushdown(int root,int l,int r){
        for(int i=0;i<=20;i++){
            if(lz[root][i]){
               int midd=(l+r)>>1;
                tr[root<<1][i]=midd-l+1-tr[root<<1][i];
                tr[root<<1|1][i]=r-midd-tr[root<<1|1][i];
                lz[root<<1][i]^=lz[root][i];
                lz[root<<1|1][i]^=lz[root][i];
                lz[root][i]=0;
            }
    
        }
    }
    void update(int L,int R,int x,int root,int l,int r){
        if(L<=l&&r<=R){
            for(int i=0;i<=20;i++)
                if(x&(1<<i)){
                    tr[root][i]=r-l+1-tr[root][i];///记录i位置二进制的个数
                    lz[root][i]^=1;
                }
            return;
    
        }
        pushdown(root,l,r);
        int midd=(l+r)>>1;
        if(L<=midd)
            update(L,R,x,lson);
        if(R>midd)
            update(L,R,x,rson);
        up(root);
    }
    ll query(int L,int R,int root,int l,int r){
        if(L<=l&&r<=R){
            ll ans=0;
            for(int i=0;i<=20;i++){
                ans+=tr[root][i]*(1ll<<i);
            }
            return ans;
        }
        pushdown(root,l,r);
        int midd=(l+r)>>1;
        ll res=0;
        if(L<=midd)
            res=query(L,R,lson);
        if(R>midd)
            res+=query(L,R,rson);
        return res;
    }
    int main(){
        int n,m;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]);
        build(1,1,n);
        scanf("%d",&m);
        while(m--){
            int op;
            scanf("%d",&op);
            if(op==1){
                int l,r;
                scanf("%d%d",&l,&r);
                printf("%lld
    ",query(l,r,1,1,n));
            }
            else{
                int l,r,x;
                scanf("%d%d%d",&l,&r,&x);
                update(l,r,x,1,1,n);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Perfect ScrollBar插件使用方法
    分享WEBAPP利用纯HTML5实现拨打电话,打开相册,打开摄像头源码
    一周心得
    19赵亮龙07杨康
    李娜跟姜山
    一周心得
    对结对编程的个人理解
    周心得和总结
    关于IT行业抄袭和借鉴
    第三周总结
  • 原文地址:https://www.cnblogs.com/starve/p/12602350.html
Copyright © 2020-2023  润新知