BZOJ 4260: Codechef REBXOR
Description
Input
输入数据的第一行包含一个整数N,表示数组中的元素个数。
第二行包含N个整数A1,A2,…,AN。
Output
输出一行包含给定表达式可能的最大值。
Sample Input
5
1 2 3 1 2
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。
Solution:
01trie树求异或和最大。
先正反都求一遍异或前缀和,每次都将当前的前缀和加入01tire树中,同时查询并更新$ln[i]$和$rn[i]$(分别表示$[1,i]$的最大连续异或和,$[i,n]$的最大连续异或和),那么答案$ans=max(ln[i]+rn[i+1])$,注意的细节是trie树要清0并在tire树中先插入一个0以便保证第一次插入的异或前缀和是其本身。
代码:
#include<bits/stdc++.h> #define il inline #define ll long long #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--) using namespace std; const int N=4e5+7; int trie[N*31][2],cnt,n,a[N],sum,ln[N],rn[N],ans; il void insert(int a){ int x,p=0; Bor(i,0,31){ x=(1<<i)&a?1:0; if(!trie[p][x])trie[p][x]=++cnt; p=trie[p][x]; } } il int search(int a){ int x,p=0,ans=0; Bor(i,0,31){ x=(1<<i)&a?0:1; if(trie[p][x])ans+=1<<i,p=trie[p][x]; else p=trie[p][x^1]; if(!p)return ans; } return ans; } il void init(){ scanf("%d",&n); For(i,1,n) scanf("%d",&a[i]); sum=0,insert(0); For(i,1,n) sum^=a[i],insert(sum),ln[i]=max(search(sum),ln[i-1]); sum=0; memset(trie,0,sizeof(trie)),cnt=0,insert(0); Bor(i,1,n) sum^=a[i],insert(sum),rn[i]=max(search(sum),rn[i+1]); For(i,1,n) ans=max(ln[i]+rn[i+1],ans); cout<<ans; } int main(){ init(); return 0; }
PS:~蒟蒻写博客不易,转载请注明出处,万分感谢!~