题目
字典树可以用来找集合中两个数的异或值的最大值
本题题意可以转换为求
max(l[i]+r[i+1])
///l[i]=a[l]^a[l+1]^...^a[r] 1<=l<=r<=i
///r[i]=a[l]^a[l+1]^...^a[r] i<=l<=r<=N
再设一个前缀异或和 利用异或的定义求出l[i] 后缀同理
x[i]=a[0]^a[1]^...^a[i]///a[0]=0
l[i]=max(x[i]^x[j])///0<=j<i
书上的AC代码
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=4e5+5;
const int Z=2;
int n,tot=1;
int ch[N<<5][Z],l[N],r[N],A[N];
void init()
{
memset(ch,0,sizeof(ch));
}
///将当前的前/后缀异或和化为31位2进制串,加入Trie树
bool Insert(int x)
{
int u=1;
for(int i=1<<30;i;i>>=1)
{
int c=(x&i)?1:0;
if(!ch[u][c])ch[u][c]=++tot;
u=ch[u][c];
}
}
int Find(int x)
{
int u=1,ans=0;
for(int i=1<<30;i;i>>=1)
{
int c=(x&i)?0:1;
if(ch[u][c])
{
ans+=i;
u=ch[u][c];
}
else u=ch[u][!c];
}
return ans;
}
int main()
{
int now,ans=0;
scanf("%d",&n);
Insert(now=0);
for(int i=1;i<=n;i++)
{
scanf("%d",&A[i]);
now^=A[i];
Insert(now);
l[i]=max(l[i-1],Find(now));
}
init();
tot=1;
Insert(now=0);
for(int i=n;i>=1;i--)
{
now^=A[i];
Insert(now);
r[i]=max(r[i+1],Find(now));
}
for(int i=1;i<n;i++)
ans=max(ans,l[i]+r[i+1]);
printf("%d\n",ans);
return 0;
}