题意:给你一个数组,有两种操作,一种区间xor一个值,一个是查询区间xor的结果的种类数 

做法一:
对于一个给定的区间,我们可以通过求解线性基的方式求出结果的种类数,而现在只不过将其放在线树上维护区间线性基。

用线段树去维护区间合并

#include <bits/stdc++.h>
 
using namespace std;
const int maxn = 1e5;
struct node {
    int bas[30],lazy,st;
    void init() {
        memset(bas,0,sizeof(bas));
        lazy = 0;st = 0;
    }
    int Count() {
        int ans = 0;
        for(int i = 0;i<=29;i++) {
            if(bas[i]) ans++;
        }
        return ans;
    }
    void add(int x) {
        for(int i = 29;i>=0;i--) {
            if((x>>i)&1){
                if(bas[i])x^=bas[i];
                else {
                    bas[i] = x;
                    break;
                }
            }
        }
    }
    node operator + (const node &a) const{
        node ans;  ans.init();
        for(int i = 0;i<=29;i++) {
            ans.add(bas[i]);
            ans.add(a.bas[i]);
        }
        ans.add(st^a.st);
        ans.st = a.st;
        return ans;
    }
}tr[8*maxn],ans;
int n,q;
void pushdown(int st) {
    if(tr[st].lazy) {
        tr[st<<1].lazy ^= tr[st].lazy;
        tr[st<<1].st ^= tr[st].lazy;
        tr[st<<1|1].lazy ^= tr[st].lazy;
        tr[st<<1|1].st ^= tr[st].lazy;
        tr[st].lazy = 0;
    }
}
void build(int l,int r,int st) {
    tr[st].init();
    if(l == r) {
        scanf("%d",&tr[st].st);
        return ;
    }
    int mid = (l+r)>>1;
    build(l,mid,st<<1);
    build(mid+1,r,st<<1|1);
    tr[st] = tr[st<<1] + tr[st<<1|1];
}
void update(int l,int r,int st,int L,int R,int d) {
    if(l>=L && r<=R) {
        tr[st].lazy ^= d;
        tr[st].st ^= d;
        return ;
    }
    pushdown(st);
    int mid = (l+r) >>1;
    if(L<=mid) update(l,mid,st<<1,L,R,d);
    if(R> mid) update(mid+1,r,st<<1|1,L,R,d);
    tr[st] = tr[st<<1] + tr[st<<1|1];
}
void Query(int l,int r,int st,int L,int R) {
    if(l >= L && r <= R) {
        ans = ans + tr[st];
        return ;
    }
    pushdown(st);
    int mid = (l+r) >>1;
    if(L<=mid) Query(l,mid,st<<1,L,R);
    if(R>mid)  Query(mid+1,r,st<<1|1,L,R);
    tr[st] = tr[st<<1] + tr[st<<1|1];
}
int main() {
    int op,l,r,d;
    scanf("%d %d",&n,&q);
    build(1,n,1);
    while(q--) {
        scanf("%d %d %d",&op,&l,&r);
        if(op == 1) {
            scanf("%d",&d);
            update(1,n,1,l,r,d);
        }
        else {
            ans.init();
            Query(1,n,1,l,r);
            printf("%d\n",1<<ans.Count());
        }
    }
    return 0;
}
View Code

相关文章: