BZOJ-4260 Codechef REBXOR(trie)
题目描述
给定一个有 \(n(2\leq n\leq 4\times 10^5)\) 个元素的数组 \(a\),下标从 \(1\) 开始,求下式的最大值:
其中 \(1\leq L_1\leq R_1\leq L_2\leq R_2\leq n\),\(\oplus\) 表示异或运算。
分析
设 \(l[i]\) 为 \(1\leq L\leq R\leq i\) 的最大的 \(a[L]\oplus a[L+1]\oplus\cdots \oplus a[R]\),\(r[i]\) 为 \(i\leq L\leq R\leq n\) 的最大的 \(a[L]\oplus a[L+1]\oplus\cdots \oplus a[R]\),则答案为 \(l[i]+r[i+1]\)。
设 \(presum[i]\) 为 \(a[0]\oplus a[1]\oplus a[2]\oplus \cdots\oplus a[i](a[0]=0)\),则 \(l[i]=\max(presum[i]\oplus presum[j])(0\leq j<i)\),把 \(presum\) 数组插入到第一棵 \(\text{trie}\) 中,尽量走相反的字符指针即可求出 \(l[i]\)。同理,设 \(sufsum[i]=a[n+1]\oplus a[n-1]\oplus\cdots\oplus a[i](a[n+1]=0)\),则 \(r[i]=\max(sufsum[i]\oplus sufsum[j])(i<j\leq n+1)\),把 \(sufsum\) 数组插入到第二棵 \(\text{trie}\) 中,尽量走相反的字符指针即可求出 \(r[i]\)。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=4e5+10;
int l[N],r[N],a[N];
int presum[N],sufsum[N];
struct Trie
{
int trie[N*30][2],tot=1;
void insert(int val)
{
int p=1;
for(int i=30;i>=0;i--)
{
int num=(val>>i)&1;
if(trie[p][num]==0)
trie[p][num]=++tot;
p=trie[p][num];
}
}
int query(int val)
{
int p=1;
long long ans=0;
for(int i=30;i>=0;i--)
{
int num=(val>>i)&1;
if(trie[p][!num])
{
ans=ans+(1<<i);
p=trie[p][!num];
}
else
p=trie[p][num];
}
return ans;
}
}A,B;
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
presum[0]=0;
A.insert(presum[0]);
for(int i=1;i<=n;i++)
{
presum[i]=presum[i-1]^a[i];
A.insert(presum[i]);
l[i]=max(l[i-1],A.query(presum[i]));
}
B.insert(0);
sufsum[n+1]=0;
for(int i=n;i>=1;i--)
{
sufsum[i]=sufsum[i+1]^a[i];
B.insert(sufsum[i]);
r[i]=max(r[i+1],B.query(sufsum[i]));
}
int ans=0;
for(int i=1;i<=n-1;i++)
ans=max(ans,l[i]+r[i+1]);
cout<<ans<<endl;
return 0;
}
posted on 2020-11-24 00:19 DestinHistoire 阅读(64) 评论(0) 收藏 举报
浙公网安备 33010602011771号