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

传送门

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

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

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

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

注意要先建一个000号点处理询问111~xxx的情况

#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';
		}
	}
}

转载于:https://www.cnblogs.com/stargazer-cyk/p/10366355.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值