题意:维护一个数列,支持区间xor修改和询问用区间中的数能异或出多少个不同的数
差分,设原序列为$a_{1\cdots n}$,差分序列为$d_{1\cdots n}$,那么用$a_l$和$d_{l+1\cdots r}$和用$a_{l\cdots r}$来异或可以得到一样的答案
所以直接用两棵线段树维护原序列和差分序列的线性基即可
差分经常被忽略,以后得注意一下...
#include<stdio.h> #include<string.h> struct lb{ int c[31],cnt; lb(){ memset(c,0,sizeof(c)); cnt=0; } void insert(int v){ for(int i=30;i>=0;i--){ if(v>>i&1){ if(c[i]==0){ c[i]=v; cnt++; return; } v^=c[i]; } } } }; lb operator+(lb a,lb b){ for(int i=0;i<31;i++){ if(b.c[i])a.insert(b.c[i]); } return a; } int a[200010]; struct seg1{ int t[800010]; void build(int l,int r,int x){ if(l==r){ t[x]=a[l]; return; } int mid=(l+r)>>1; build(l,mid,x<<1); build(mid+1,r,x<<1|1); } void pushdown(int x){ if(t[x]){ t[x<<1]^=t[x]; t[x<<1|1]^=t[x]; t[x]=0; } } void modify(int L,int R,int v,int l,int r,int x){ if(L<=l&&r<=R){ t[x]^=v; return; } int mid=(l+r)>>1; pushdown(x); if(L<=mid)modify(L,R,v,l,mid,x<<1); if(mid<R)modify(L,R,v,mid+1,r,x<<1|1); } int query(int p,int l,int r,int x){ if(l==r)return t[x]; int mid=(l+r)>>1; pushdown(x); if(p<=mid) return query(p,l,mid,x<<1); else return query(p,mid+1,r,x<<1|1); } }s1; int d[200010]; struct seg2{ lb t[800010]; void pushup(int x){ t[x]=t[x<<1]+t[x<<1|1]; } void build(int l,int r,int x){ if(l==r)return t[x].insert(d[l]); int mid=(l+r)>>1; build(l,mid,x<<1); build(mid+1,r,x<<1|1); pushup(x); } void modify(int p,int l,int r,int x){ if(l==r){ t[x]=lb(); return t[x].insert(d[l]); } int mid=(l+r)>>1; if(p<=mid) modify(p,l,mid,x<<1); else modify(p,mid+1,r,x<<1|1); pushup(x); } lb query(int L,int R,int l,int r,int x){ if(L<=l&&r<=R)return t[x]; int mid=(l+r)>>1; if(R<=mid)return query(L,R,l,mid,x<<1); if(mid<L)return query(L,R,mid+1,r,x<<1|1); return query(L,R,l,mid,x<<1)+query(L,R,mid+1,r,x<<1|1); } }s2; int main(){ int n,m,i,l,r,k; lb t; scanf("%d%d",&n,&m); for(i=1;i<=n;i++)scanf("%d",a+i); s1.build(1,n,1); for(i=1;i<=n;i++)d[i]=a[i-1]^a[i]; s2.build(1,n,1); while(m--){ scanf("%d%d%d",&i,&l,&r); if(i==1){ scanf("%d",&k); s1.modify(l,r,k,1,n,1); d[l]^=k; s2.modify(l,1,n,1); if(r<n){ d[r+1]^=k; s2.modify(r+1,1,n,1); } }else{ t=l<r?s2.query(l+1,r,1,n,1):lb(); t.insert(s1.query(l,1,n,1)); printf("%d\n",1<<t.cnt); } } }