题目大意:给定一个长度为 n 的序列,求 1≤l1≤r1<l2≤r2≤n 使得 (⊕r1i=l1ai)+(⊕r2i=l2ai) 最大,输出这个最大值
傻逼题……
求前缀和,问题转化成了求 0≤l1<r1≤l2<r2≤n 使得 (al1⊕ar1)+(al2⊕ar2) 最大
从大到小枚举 r1 ,边枚举边记录最大的 al2⊕ar2 ,然后求出最大的 al1⊕ar1
用可持久化Trie树即可完成上述操作
时间复杂度 O(nlogn)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 400400
using namespace std;
int n,ans,_max;
int a[M];
struct Trie{
Trie* son[2];
int size;
#define ls son[0]
#define rs son[1]
void* operator new (size_t,Trie *_,Trie *__,int ___)
{
static Trie mempool[M*32],*C=mempool;
C->ls=_;
C->rs=__;
C->size=___;
return C++;
}
friend Trie* Insert(Trie *p,int x,int digit)
{
if(!digit)
return new (p->ls,p->rs,p->size+1)Trie;
if(x&digit)
return new (p->ls,Insert(p->rs,x,digit>>1),p->size+1)Trie;
else
return new (Insert(p->ls,x,digit>>1),p->rs,p->size+1)Trie;
}
friend int Query(Trie *p1,Trie *p2,int x,int digit)
{
if(!digit)
return 0;
if(p1->son[bool(~x&digit)]->size - p2->son[bool(~x&digit)]->size)
return digit | Query(p1->son[bool(~x&digit)],p2->son[bool(~x&digit)],x,digit>>1);
else
return Query(p1->son[bool(x&digit)],p2->son[bool(x&digit)],x,digit>>1);
}
}*mem[M],**tree=mem+1;
int main()
{
int i;
cin>>n;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
a[i]^=a[i-1];
}
tree[-1]=new (0x0,0x0,0)Trie;
tree[-1]->ls=tree[-1]->rs=tree[-1];
for(i=0;i<=n;i++)
tree[i]=Insert(tree[i-1],a[i],1<<29);
for(i=n-1;i;i--)
{
_max=max(_max,Query(tree[n],tree[i],a[i],1<<29));
ans=max(ans,_max+Query(tree[i],tree[-1],a[i],1<<29));
}
cout<<ans<<endl;
return 0;
}