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;
}

posted @ 2018-02-03 08:50  PIPIBoss  阅读(159)  评论(0编辑  收藏  举报