题意:给你一个数组,有两种操作,一种区间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; }