zoukankan      html  css  js  c++  java
  • CF-242E XOR on Segment [线段树]

    题目链接

    题意:有n个数,m个操作。操作有两种,操作1是查询 [l, r] 的区间和,操作2是将区间 [l, r] 的每一位异或x。

    思路:按二进制位建树,每个节点用于统计1的个数,添加懒惰标记,记录该节点是否异或,同时需要异或是就用该节点的区间长度减去1的个数更新

    感想:线段树真神奇

    #include <bits/stdc++.h>
    const int maxn = 100005;
    using namespace std;
    typedef long long ll;
    int sum[26][maxn<<2];
    bool lazy[26][maxn<<2];
    int ans[26];
    
    void fen(int x, int pos){
        int ji = 0;
        while(x){
            sum[ji++][pos] = x%2;
            x/=2;
        }
    }
    
    void fen1(int x, int pos, int len){
        int ji = 0;
        while(x){
            if(x%2){
                sum[ji][pos] = len - sum[ji][pos];
                lazy[ji][pos] = lazy[ji][pos]^1;
            }
            x/=2;
            ji++;
        }
    }
    
    void shang(int rt){
        for(int i=0; i<22; i++){
            sum[i][rt] = sum[i][rt<<1] + sum[i][rt<<1|1];
        }
    }
    void xia(int rt, int len){
        for(int i=0; i<22; i++){
            if(lazy[i][rt]){
                sum[i][rt<<1] = (len - (len>>1)) - sum[i][rt<<1];
                sum[i][rt<<1|1] = (len>>1) - sum[i][rt<<1|1];
                lazy[i][rt<<1] ^= 1;
                lazy[i][rt<<1|1] ^= 1;
                lazy[i][rt] = 0;
            }
        }
    }
    
    void chuang(int l, int r, int rt){
        if(l == r){
            int t;
            scanf("%d", &t);
            fen(t, rt);//将该位上的数分解到每一颗树的相
            return ;
        }
        int m = (l+r)>>1;
        chuang(l, m, rt<<1);
        chuang(m+1, r, rt<<1|1);
        shang(rt);
    }
    
    void geng(int l, int r, int rt, int L, int R, int x){//更新维护
        if(L <= l && R >=r){
            fen1(x, rt, r-l+1);
            return ;
        }
        int m = (l+r)>>1;
        xia(rt, r-l+1);
        if(L <= m)
            geng(l, m, rt<<1, L, R, x);
        if(R > m)
            geng(m+1, r, rt<<1|1, L, R, x);
        shang(rt);
    }
    void cha(int l, int r, int rt, int L, int R){//查询
        if(L<=l && R>=r){
            for(int i=0; i<22; i++)
                ans[i] += sum[i][rt];
            return ;
        }
        int m = (l+r)>>1;
        xia(rt, r-l+1);
        if(L <= m)
            cha(l, m, rt<<1, L, R);
        if(R > m)
            cha(m+1, r, rt<<1|1, L, R);
    }
    
    
    int main()
    {
        int n;
        scanf("%d", &n);
        chuang(1, n, 1);//创建树
        int m;
        scanf("%d", &m);
        while(m--){
            int op, l, r;
            scanf("%d%d%d", &op, &l, &r);
            if(op == 1){
                memset(ans, 0, sizeof(ans));
                cha(1, n, 1, l, r);
                ll he = 0;
                for(int i=21; i>=0; i--){
                    he = he*2L + ans[i]*1L;
                }
                cout<<he<<endl;
            }
            else{
                int x;
                scanf("%d", &x);
                geng(1, n, 1, l, r, x);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    iframe高度100%,自适应高度
    怎么让frameset出现整体滚动条
    页面返回顶部
    HTML页面跳转的5种方法
    java web中路径问题。
    sql server数据库添加记录
    如何获取新浪微博背景图
    JavaScript检查是否包含某个字符
    纯JS省市区三级联动
    document.getElementById方法在火狐和谷歌浏览器兼容
  • 原文地址:https://www.cnblogs.com/jizhihong/p/13337367.html
Copyright © 2011-2022 走看看