1014 - 可持久化trie树 - 最大异或和(BZOJ 3261)

传送门

 

分析

添加操作很好办,我们先放一放

来看询问操作

a[p]xora[p+1] xor .....xor a[n]xor X求最大

我们知道xor有自反性

所以上面那个式子就等价于 S[p-1]xor S[n]xor X(令S[i]=a[1] xor a[2] xor .... xor a[i])

又因为后面两个是可以看做定值,我们令Val=S[n] xor X

现在问题就转化为当p>=l&&p<=r时,找到一个S使得S xor Val的值最大

这就是一个很经典的区间异或最大值了,我们用可持久化trie树来实现

需要注意几点:

  1. 由于我们找的是S[p-1] 所以为了避免查询的时候访问到了负数,我们在S[]数组中多放一个0,也就是说S[1] = 0
  2. (x>>i )&1和(1<<i)&x,这两个是不一样的,前者只会出现0或1,后者只有当 x 对应的那一位为0时,才是0
  3. cin慢到飞起……用cin 3000多ms,改成scanf后直接A了

 

代码

空间随便开的……不具备参考性

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 300009
#define in read()
using namespace std;
inline int read(){
	char ch;int f=1,res=0;
	while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
	while(ch>='0'&&ch<='9'){
		res=(res<<3)+(res<<1)+ch-'0';
		ch=getchar();
	}
	return f==1?res:-res;
}
int n,m,a,rt[300005*100],tot=0;
struct node{
	int cnt,l,r;
}tr[300005*100];
inline void insert(int pre,int &now,int x,int dep){
	tr[now=++tot]=tr[pre];
	tr[now].cnt++;
	if(dep==-1) return;
	//int c=x&(1<<dep);
	int c=(x>>dep)&1;
	if(!c)	insert(tr[pre].l,tr[now].l,x,dep-1);
	else insert(tr[pre].r,tr[now].r,x,dep-1);
}
int ans=0;
inline void query(int R,int L,int x,int dep){
	if(dep==-1) return ;
//	int c=x&(1<<dep);
	int c=(x>>dep)&1;
	c^=1;
	if(!c) {
		if(tr[tr[R].l].cnt-tr[tr[L].l].cnt) ans=ans|(1<<dep),query(tr[R].l,tr[L].l,x,dep-1);
		else query(tr[R].r,tr[L].r,x,dep-1);
	}
	else{
		if(tr[tr[R].r].cnt-tr[tr[L].r].cnt) ans=ans|(1<<dep),query(tr[R].r,tr[L].r,x,dep-1);
		else query(tr[R].l,tr[L].l,x,dep-1);
	}
}
int sum[600005];
int main(){
	n=in;m=in;n++;
	int i,j,k;
	rt[0]=0;
	for(i=2;i<=n;++i){//从2开始
		sum[i]=sum[i-1]^in;
	}
	for(i=1;i<=n;++i)
		insert(rt[i-1],rt[i],sum[i],25);
	char ch[5];
	int x,l,r;
	for(i=1;i<=m;++i){
		scanf("%s",ch);
		if(ch[0]=='A'){
			x=in;
			++n;sum[n]=sum[n-1]^x;
			insert(rt[n-1],rt[n],sum[n],25);
		}
		else{
			l=in;r=in;x=in^sum[n];
			ans=0;
			query(rt[r],rt[l-1],x,25);
			cout<<ans<<'\n';
		}
	}
	return 0;
}

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值