[CF587E]Duff as a Queen

题意:维护一个数列,支持区间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);
		}
	}
}

猜你喜欢

转载自www.cnblogs.com/jefflyy/p/9510402.html