题意:找一个前缀和一个后缀,使其异或的结果最大。
思路:对于一个后缀,将他前面的所有的前缀加到一个Trie树中,然后根据这个后缀数每个位上的0和1,寻找使其异或最大的数。
AC代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
ll val[100010],pri[100010],past[100010],pow2[50],num,ans;
struct Trie
{ int index;
Trie *next[2];
Trie()
{ index=-1;
memset(next,0,sizeof(next));
}
};
Trie *root=new Trie;
void Trie_Insert(Trie *tr,ll k,int pos)
{ ll p=k%pow2[pos+1]/pow2[pos];
if(pos>=1)
{ if(tr->next[p]==0)
tr->next[p]=new Trie;
Trie_Insert(tr->next[p],k,pos-1);
}
else
tr->index=1;
}
void Trie_Search(Trie *tr,ll k,int pos)
{ ll p=k%pow2[pos+1]/pow2[pos];
if(pos>0)
{ if(p==0)
{ if(tr->next[1]!=0)
{ num+=pow2[pos];
Trie_Search(tr->next[1],k,pos-1);
}
else
Trie_Search(tr->next[0],k,pos-1);
}
if(p==1)
{ if(tr->next[0]!=0)
Trie_Search(tr->next[0],k,pos-1);
else
{ num+=pow2[pos];
Trie_Search(tr->next[1],k,pos-1);
}
}
}
}
int main()
{ int n,m,i,j,k;
scanf("%d",&n);
pow2[0]=1;
pow2[1]=1;
for(i=2;i<=42;i++)
pow2[i]=pow2[i-1]*2;
for(i=1;i<=n;i++)
scanf("%I64d",&val[i]);
for(i=1;i<=n;i++)
pri[i]=pri[i-1]^val[i];
for(i=n;i>=1;i--)
past[i]=past[i+1]^val[i];
Trie_Insert(root,0,40);
for(i=1;i<=n+1;i++)
{ num=0;
Trie_Search(root,past[i],40);
ans=max(ans,past[i]^num);
Trie_Insert(root,pri[i],40);
}
printf("%I64d\n",ans);
}