Evanyou Blog 彩带

BZOJ 4260: Codechef REBXOR

Description

 

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。

 

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;
}

 

posted @ 2018-08-14 21:18  five20  阅读(123)  评论(0编辑  收藏  举报
Live2D