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;
}
posted @ 2023-11-06 22:09  SError  阅读(7)  评论(0编辑  收藏  举报