bzoj3261: 最大异或和(可持久化字典树)

Problem

给定一个非负整数序列 a {a} a,初始长度为 n n n
有M个操作,有以下两种操作类型:
1 、 A 1、A 1A $ x$:添加操作,表示在序列末尾添加一个数 x x x ,序列的长度 n + 1 n+1 n+1
2 、 Q 2、Q 2Q $ l$ $ r$ $ x$:询问操作,你需要找到一个位置 p p p,满足 l < = p < = r l<=p<=r l<=p<=r,使得:
a [ p ] a[p] a[p] x o r xor xor a [ p + 1 ] a[p+1] a[p+1] x o r xor xor . . . ... ... x o r xor xor a [ N ] a[N] a[N] x o r xor xor x x x 最大,输出最大是多少。

Solution

可持久化字典树…

Code

#include 
#define N 600010
int n,m,tot=0,a[N],rt[N],sum,bin[30];
char op[5];
struct Node{int son[2],sz;}tree[N*30];
inline void ins(int &rt,int x){
	tree[++tot]=tree[rt];rt=tot;
	int p=tot;tree[p].sz++; 
	for(int i=23;i>=0;i--){
		bool opt=x&bin[i];
		tree[++tot]=tree[tree[p].son[opt]]; 
		tree[p].son[opt]=tot;
		p=tot;
		tree[p].sz++; 
	}
}
inline int query(int p,int v,int x){
	int ans=0;
	for(int i=23;i>=0;i--){
		bool opt=bin[i]&x;opt^=1;
		if(tree[tree[v].son[opt]].sz-tree[tree[p].son[opt]].sz>=1)
			ans|=bin[i],p=tree[p].son[opt],v=tree[v].son[opt];
		else p=tree[p].son[opt^1],v=tree[v].son[opt^1];
	}
	return ans;
}
int main(){
//	freopen("a.in","r",stdin);
	scanf("%d%d",&n,&m);n++;
	bin[0]=1;for(int i=1;i<=23;i++) bin[i]=bin[i-1]<<1;
	ins(rt[1],0);
	for(int i=2;i<=n;i++){
		scanf("%d",&a[i]);
		sum^=a[i];rt[i]=rt[i-1];
		ins(rt[i],sum);
	}
	while(m--){
		scanf("%s",op+1);
		if(op[1]=='A'){
			int x;scanf("%d",&x);
			sum^=x;n++;
			rt[n]=rt[n-1];
			ins(rt[n],sum);
		}else{
			int l,r,x;scanf("%d%d%d",&l,&r,&x);
			printf("%d\n",query(rt[l-1],rt[r],x^sum));
		}
	}
	return 0;
}

你可能感兴趣的:(字典树,学习笔记)