【BZOJ3261】— 最大异或和(可持久化0/1Trie)

传送门

终于开始学可持久化数据结构了

考虑到类似于主席树,每次加一个数只会增加loglog个节点

所以就直接对于每一次的0/1Trie0/1Trie每个节点记录一个sumsum表示前ii个数中有多少个数经过了这个点

询问的时候看一下sum[r]sum[l1]=0sum[r]-sum[l-1]=0?就知道ll~rr之间存不存在数经过该点了

注意要先建一个00号点处理询问11~xx的情况

#include<bits/stdc++.h>
using namespace std;
#define gc getchar
inline int read(){
	char ch=gc();int res=0,f=1;
	while(!isdigit(ch)){if(ch=='-')f=-f;ch=gc();}
	while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=gc();
	return res*f;
}
#undef gc
const int N=600005;
const int Log=25;
int n,m,a[N],b[N],rt[N],sum[N*Log],son[N*Log][2],cnt;
inline int insert(int u,int val){
	int tmp=++cnt,now=cnt;
	for(int i=Log-1;~i;i--){
		son[now][1]=son[u][1],son[now][0]=son[u][0];
		sum[now]=sum[u]+1;int t=(val&(1<<i))?1:0;
		u=son[u][t],son[now][t]=++cnt,now=cnt;
	}
	sum[now]=sum[u]+1;return tmp;
}
inline int query(int l,int r,int val){
	int tmp=0;
	for(int i=Log-1;~i;i--){
		int t=(val&(1<<i))?1:0;
		if(sum[son[r][t^1]]-sum[son[l][t^1]])
		tmp+=(1<<i),r=son[r][t^1],l=son[l][t^1];
		else r=son[r][t],l=son[l][t];
	}
	return tmp;
} 
int main(){
	n=read(),m=read();
	for(int i=1;i<=n;i++)a[i]=read();
	for(int i=0;i<=n;i++)b[i]=b[i-1]^a[i];
	rt[0]=insert(0,0);
	for(int i=0;i<=n;i++)rt[i]=insert(rt[i-1],b[i]);
	char c[5];
	for(int i=1;i<=m;i++){
		scanf("%s",c);
		if(c[0]=='A'){
			n++,a[n]=read(),b[n]=b[n-1]^a[n];
			rt[n]=insert(rt[n-1],b[n]);
		}
		else{
			int l=read()-1,r=read()-1,k=read();
			cout<<query(rt[l-1],rt[r],b[n]^k)<<'\n';
		}
	}
}
posted @ 2019-01-16 20:26  Stargazer_cykoi  阅读(127)  评论(0编辑  收藏  举报