NKOJ3572 BZOJ4260 Codechef REBXOR
问题描述
输入格式
输入数据的第一行包含一个整数N,表示数组中的元素个数。
第二行包含N个整数A1,A2,…,An。
输出格式
输出一行包含给定表达式可能的最大值。
样例输入 1
5
1 2 3 1 2
样例输出 1
6
样例输入 2
10
9 10 6 0 4 4 9 7 8 9
样例输出 2
30
数据范围
对于100%的数据,2<=N<=4*10^5,0<=Ai<=10^9。
处理两段也比较简单,用一个前缀异或和和一个后缀异或和就可以解决了。用同样的方法处理出每个点左边一段区间的最大异或和和右边一段区间的最大异或和即可。
代码:
#include<stdio.h>
#include<cstring>
#define MAXN 400005
int N,data[MAXN],psum[MAXN],ssum[MAXN],pAns[MAXN],sAns[MAXN],Ans;
int Son[MAXN*32][2],rt=1,tot=1;
void Insert(int x)
{
int i,p,t;
for(i=29,p=rt;i>=0;i--,p=Son[p][t])
{
t=x>>i&1;
if(!Son[p][t])Son[p][t]=++tot;
}
}
int FindAns(int x)
{
int p,t,i,ans=0,tmp;
for(i=29,p=rt;i>=0;i--)
{
t=x>>i&1;
if(Son[p][t^1])ans|=(1<<i),p=Son[p][t^1];
else p=Son[p][t];
}
return ans;
}
int main()
{
int i,j;
scanf("%d",&N);
for(i=1;i<=N;i++)scanf("%d",&data[i]);
for(i=1;i<=N;i++)psum[i]=psum[i-1]^data[i];
for(i=N;i;i--)ssum[i]=ssum[i+1]^data[i];
Insert(0);
for(i=1;i<=N;i++)
{
Insert(psum[i]);
pAns[i]=FindAns(psum[i]);
if(pAns[i]<pAns[i-1])pAns[i]=pAns[i-1];
}
memset(Son,0,sizeof(Son));tot=1;
for(i=N+1;i;i--)
{
Insert(ssum[i]);
sAns[i]=FindAns(ssum[i]);
if(sAns[i]<sAns[i+1])sAns[i]=sAns[i+1];
}
for(i=1;i<N;i++)if(pAns[i]+sAns[i+1]>Ans)Ans=pAns[i]+sAns[i+1];
printf("%d",Ans);
}