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;
}
原文地址:https://www.cnblogs.com/jizhihong/p/13337367.html