[bzoj4260]Codechef REBXOR【trie树】
【题目链接】
http://www.lydsy.com/JudgeOnline/problem.php?id=4260
【题解】
一段的异或和可以转换为两个前缀的异或。
因此可以用trie树预处理出任意一个节点向左或向右的最大异或。
然后求出前缀/后缀最大值,枚举断点即可。
/* --------------
user Vanisher
problem bzoj-4260
----------------*/
# include <bits/stdc++.h>
# define ll long long
# define inf 0x3f3f3f3f
# define K 29
# define N 400010
using namespace std;
int read(){
int tmp=0, fh=1; char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
return tmp*fh;
}
struct node{
int son[2];
}T[N*31];
int ml[N],mr[N],s[N],place,n,a[N],ans;
void extend(int x){
int p=0,j;
for (int i=K; i>=0; i--){
if ((x&(1<<i))==0)
j=0; else j=1;
if (T[p].son[j]==0){
T[p].son[j]=++place;
p=T[p].son[j];
}
else p=T[p].son[j];
}
}
int query(int x){
int p=0, num=0, j;
for (int i=K; i>=0; i--){
if ((x&(1<<i))==0)
j=0; else j=1;
if (T[p].son[j^1]!=0){
num=num+(1<<i);
p=T[p].son[j^1];
}
else p=T[p].son[j];
}
return num;
}
int main(){
n=read();
for (int i=1; i<=n; i++)
a[i]=read();
for (int i=1; i<=n; i++)
s[i]=s[i-1]^a[i];
for (int i=1; i<=n; i++){
extend(s[i-1]);
ml[i]=max(query(s[i]),ml[i-1]);
}
memset(T,0,sizeof(T)); place=0;
for (int i=n; i>=1; i--)
s[i]=s[i+1]^a[i];
for (int i=n; i>=1; i--){
extend(s[i+1]);
mr[i]=max(query(s[i]),mr[i+1]);
}
for (int i=1; i<n; i++)
ans=max(ans,ml[i]+mr[i+1]);
printf("%d\n",ans);
return 0;
}