Input
输入数据的第一行包含一个整数N,表示数组中的元素个数。
第二行包含N个整数A1,A2,…,AN。
Output
输出一行包含给定表达式可能的最大值。
Sample Input
5
1 2 3 1 2
Sample Output
6
Hint
满足条件的(l1,r1,l2,r2)有:(1,2,3,3),(1,2,4,5),(3,3,4,5)。
对于100%的数据,2 ≤ N ≤ 4*105,0 ≤ Ai ≤ 109。
做了几个求区间异或最大的题目。求区间异或最大就是求个前缀,然后就是普通的01字典树了。
就像这个题目,求两个不相交的区间,然后两个区间的异或和最大。
我们想求一个前缀区间异或最大值并且记录下来存到数组中,然后再去枚举后缀的区间,再去更新最大值。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<string>
#define ll long long
using namespace std;
const int maxx=4e5+100;
struct node{
int trie[2];
int num;
}p[maxx*33];
int sum[maxx],pre[maxx];
int a[maxx],dp[maxx];
int n,tot;
inline void Insert(int x)
{
int root=0;
int id;
for(int i=32;i>=0;i--)
{
id=(x>>i)&1;
if(!p[root].trie[id]) p[root].trie[id]=++tot;
root=p[root].trie[id];
}
p[root].num=x;
}
inline int Find(int x)
{
int root=0;
int id;
for(int i=32;i>=0;i--)
{
id=(x>>i)&1;
if(p[root].trie[id^1]) root=p[root].trie[id^1];
else root=p[root].trie[id];
}
return p[root].num^x;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
tot=0;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) sum[i]=sum[i-1]^a[i];//前缀
for(int i=n;i>=1;i--) pre[i]=pre[i+1]^a[i];//后缀
Insert(0);
for(int i=1;i<=n;i++)
{
dp[i]=max(dp[i-1],Find(sum[i]));
Insert(sum[i]);
}
int _max=0;
for(int i=n;i>=1;i--)
{
_max=max(_max,Find(pre[i])+dp[i-1]);//枚举后缀区间异或最大值再加上前面求过的前缀,他们的和去更新最大值
Insert(pre[i]);
}
printf("%d\n",_max);
}
return 0;
}
努力加油a啊,(o)/~