bzoj 4260: Codechef REBXOR
Description
Solution
记录前缀答案和后缀答案,然后枚举断点合并即可
求出以每一个结尾的最大异或的段,相当于求两个前缀异或值的最大值,用trie树贪心即可
#include<bits/stdc++.h>
using namespace std;
const int N=400005;
int n,a[N],f[N],bin[N],rt=0,ch[N*30][2],cnt=0;
inline int qry(int x,int d,int v){
if(d==-1)return 0;
if(v&bin[d]){
if(ch[x][0])return qry(ch[x][0],d-1,v)|bin[d];
return qry(ch[x][1],d-1,v);
}
else{
if(ch[x][1])return qry(ch[x][1],d-1,v)|bin[d];
return qry(ch[x][0],d-1,v);
}
}
inline void ins(int &x,int d,int v){
if(!x)x=++cnt;
if(d==-1)return ;
ins(ch[x][(v&bin[d])>0],d-1,v);
}
int main(){
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
bin[0]=1;for(int i=1;i<=30;i++)bin[i]=bin[i-1]<<1;
int sum=0,ans=0;
ins(rt,30,0);
for(int i=1;i<=n;i++){
sum^=a[i];
f[i]=max(f[i-1],qry(rt,30,sum));
ins(rt,30,sum);
}
sum=0;rt=0;cnt=0;
memset(ch,0,sizeof(ch));
ins(rt,30,0);
for(int i=n;i>=2;i--){
sum^=a[i];
ans=max(ans,f[i-1]+qry(rt,30,sum));
ins(rt,30,sum);
}
printf("%d\n",ans);
return 0;
}