CF587E Duff as a Queen
维护序列,支持:
-
区间异或
-
查询区间子集异或值种数(包含空集)
\(n\le 2\times 10^5\),\(1\le q\le 4\times 10^4\),值域 \([1,10^9]\),TL=7s。
经典题。
操作 2 相当于查询区间线性基大小。
由于不能维护区间异或,作差分 \(b_i=a_i\oplus a_{i-1}\)。
可以得到 \(a_i=b_1\oplus \dots\oplus b_i\)。
不难发现 \(a_l,\dots,a_r\) 的张成空间与 \(a_l,b_{l+1},\dots b_r\) 相同,即两者的线性基等价。
操作 \(1\) 相当于单点异或,用线段树维护,查询时加入 \(a_l\) 查询线性基大小即可。
时间复杂度 \(O(q\log n\log^2 V)\)。
#include<bits/stdc++.h>
#define N 200010
#define M 31
using namespace std;
int read(){
int x=0,w=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*w;
}
struct Lnbs{
int p[M],siz;
Lnbs(){memset(p,0,sizeof(p)),siz=0;}
void clr(){memset(p,0,sizeof(p)),siz=0;}
void ins(int x){
if(!x)return;
for(int i=M-1;~i;i--){
if(!(x>>i))continue;
if(!p[i])return p[i]=x,siz++,void();
x^=p[i];
}
}
friend Lnbs operator +(const Lnbs &x,const Lnbs &y){
Lnbs ret=x;
for(int i=M-1;~i;i--)
if(y.p[i])ret.ins(y.p[i]);
return ret;
}
}B[N<<2];
int dat[N<<2],tag[N<<2];
int n,m,a[N],b[N],p2[M];
#define ls p<<1
#define rs p<<1|1
void pushup(int p){
B[p]=B[ls]+B[rs];
}
void pushdown(int p){
if(!tag[p])return;
dat[ls]^=tag[p],dat[rs]^=tag[p];
tag[ls]^=tag[p],tag[rs]^=tag[p],tag[p]=0;
}
void build(int p,int l,int r){
if(l==r)return B[p].ins(b[l]),dat[p]=a[l],void();
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(p);
}
void modify(int p,int l,int r,int L,int R,int v){
if(L<=l&&r<=R)return dat[p]^=v,tag[p]^=v,void();
int mid=(l+r)>>1;pushdown(p);
if(L<=mid)modify(ls,l,mid,L,R,v);
if(R>mid)modify(rs,mid+1,r,L,R,v);
}
void update(int p,int l,int r,int x){
if(l==r)return B[p].clr(),B[p].ins(b[l]),void();
int mid=(l+r)>>1;
(x<=mid)?update(ls,l,mid,x):update(rs,mid+1,r,x);
pushup(p);
}
Lnbs query(int p,int l,int r,int L,int R){
if(L<=l&&r<=R)return B[p];
int mid=(l+r)>>1;
if(R<=mid)return query(ls,l,mid,L,R);
if(L>mid)return query(rs,mid+1,r,L,R);
return query(ls,l,mid,L,R)+query(rs,mid+1,r,L,R);
}
int getval(int p,int l,int r,int x){
if(l==r)return dat[p];
int mid=(l+r)>>1;pushdown(p);
return (x<=mid)?getval(ls,l,mid,x):getval(rs,mid+1,r,x);
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;i++)
a[i]=read(),b[i]=a[i]^a[i-1];
p2[0]=1;
for(int i=1;i<M;i++)p2[i]=(p2[i-1]<<1);
build(1,1,n);
for(int opt,l,r,v;m;m--){
opt=read(),l=read(),r=read();
if(opt==1){
v=read(),b[l]^=v,b[r+1]^=v;
update(1,1,n,l);
if(r<n)update(1,1,n,r+1);
modify(1,1,n,l,r,v);
}
if(opt==2){
Lnbs cur;
if(l<r)cur=query(1,1,n,l+1,r);
cur.ins(getval(1,1,n,l));
printf("%d\n",p2[cur.siz]);
}
}
return 0;
}