bzoj 4260 REBXOR —— Trie树

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4260

用 Trie 树可以找出前缀异或的最大值和后缀异或的最大值,拼起来即可;

注意要先加入一个0,表示区间左端点在 0 或右端点在 n+1;

竟然1A了!感动。

——然后发现3个月前做过!!!... https://www.cnblogs.com/Zinn/p/9301536.html

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int const xn=4e5+5,mx=30;
int n,cnt,a[xn],pr[xn],sc[xn],c[xn*mx][2],bin[mx+5];
int rd()
{
  int ret=0,f=1; char ch=getchar();
  while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
  while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
  return f?ret:-ret;
}
void init()
{
  bin[0]=1;
  for(int i=1;i<=mx;i++)bin[i]=bin[i-1]*2;
}
void add(int x)
{
  int nw=0;
  for(int i=mx;i>=0;i--)
    {
      bool d=(x&bin[i]);
      if(!c[nw][d])c[nw][d]=++cnt; nw=c[nw][d];
    }
}
int query(int x)
{
  int nw=0,ret=0;
  for(int i=mx;i>=0;i--)
    {
      bool d=!(x&bin[i]);
      if(c[nw][d])nw=c[nw][d],ret+=bin[i];
      else nw=c[nw][!d];
    }
  return ret;
}
int main()
{
  n=rd(); init(); add(0);//
  for(int i=1,x,s=0;i<=n;i++)
    {
      x=rd(); a[i]=x; s^=x;
      pr[i]=max(pr[i-1],query(s)); add(s);
    }
  cnt=0; memset(c,0,sizeof c); add(0);
  for(int i=n,s=0;i;i--)
    {
      s^=a[i];
      sc[i]=max(sc[i+1],query(s)); add(s);
    }
  int ans=0;
  for(int i=1;i<n;i++)ans=max(ans,pr[i]+sc[i+1]);
  printf("%d\n",ans);
  return 0;
}

 

posted @ 2018-10-17 15:21  Zinn  阅读(139)  评论(0编辑  收藏  举报