#线性基,差分,线段树#洛谷 5607 [Ynoi2013] 无力回天 NOI2017


题目


分析

考虑区间修改比较难操作,将数组差分一下,转化成两次单点修改。

这样查询前缀的异或值就是该位置的异或值,线性基可以用线段树维护,

那么取出 \((l,r]\) 所在的线性基,再将 \(a[l]\) 扔入线性基查询最大异或值即可

因为如果要取出 \(a_x\) 实则就是取出 \(a_l\) xor \(b_{l+1}\) xor \(\dots\) xor \(b_x\)

所以区间异或有时转化成差分加单点异或,维护区间线性基可以这样做。


代码

#include 
#include 
#include 
#define rr register
using namespace std;
const int N=50011;
int a[N],n,m;
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline void print(int ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
struct Vector_Space{
	int re[30],now;
	inline void BUILD(){memset(re,0,sizeof(re));}
	inline void Insert(int x){
		for (rr int i=29;~i;--i)
		if ((x>>i)&1){
			if (re[i]) x^=re[i];
			    else {re[i]=x; return;}
		}
	}
	inline signed query(int x){
		for (rr int i=29;~i;--i)
		    if ((x^re[i])>x) x^=re[i];
		return x;
	}
}w[N<<2];
inline Vector_Space Merge(Vector_Space A,Vector_Space B){
	for (rr int i=29;~i;--i)
	    if (B.re[i]) A.Insert(B.re[i]);
	A.now^=B.now;
	return A;
}
inline void build(int k,int l,int r){
	if (l==r) {w[k].Insert(w[k].now^=a[l]); return;}
	rr int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	w[k]=Merge(w[k<<1],w[k<<1|1]);
}
inline void update(int k,int l,int r,int x,int y){
	if (l==r) {w[k].BUILD(),w[k].Insert(w[k].now^=y); return;}
	rr int mid=(l+r)>>1;
	if (x<=mid) update(k<<1,l,mid,x,y);
	    else update(k<<1|1,mid+1,r,x,y);
	w[k]=Merge(w[k<<1],w[k<<1|1]);
}
inline signed query(int k,int l,int r,int x){
	if (l==r) return w[k].now;
	rr int mid=(l+r)>>1;
	if (x<=mid) return query(k<<1,l,mid,x);
	    else return query(k<<1|1,mid+1,r,x)^w[k<<1].now;//前缀xor
}
inline Vector_Space Query(int k,int l,int r,int x,int y){
	if (l==x&&r==y) return w[k];
	rr int mid=(l+r)>>1;
	if (y<=mid) return Query(k<<1,l,mid,x,y);
	else if (x>mid) return Query(k<<1|1,mid+1,r,x,y);
	    else return Merge(Query(k<<1,l,mid,x,mid),Query(k<<1|1,mid+1,r,mid+1,y));
}
signed main(){
	n=iut(); m=iut();
	for (rr int i=1;i<=n;++i) a[i]=iut();
	for (rr int i=n;i>1;--i) a[i]^=a[i-1];
	build(1,1,n);
	for (rr int i=1;i<=m;++i){
		rr int opt=iut(),l=iut(),r=iut(),x=iut();
		if (opt==1){
			update(1,1,n,l,x);
			if (r(x^Al)?x:(x^Al)),putchar(10); continue;}
			rr Vector_Space t=Query(1,1,n,l+1,r);
			t.Insert(Al),print(t.query(x)),putchar(10);
		}
	}
	return 0;
}

相关