1. 程式人生 > >[bzoj4260]Codechef REBXOR

[bzoj4260]Codechef REBXOR

一個 分享 string span efi 數據 ring 需要 hint

傳送門

Description

技術分享圖片

Input

輸入數據的第一行包含一個整數\(N\),表示數組中的元素個數。

第二行包含N個整數\(A_1,A_2..A_N\)

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*10^5,0 ≤ Ai ≤ 10^9\)

Solution

這道題相當妙啊……

首先將數組分割成兩部分。

\(lmax[i]\)為原數組\([1,i]\)

中的最大異或值,\(rmax[i]\)為原數組\([i,N]\)的最大異或值。

則我們只需要求出最大的\(lmax[i]+rmax[i+1]\)即可。

那麽對於\(lmax[i]\)\(rmax[i]\)的求法:

\(Prefix[i]\)為原數組的前綴異或,對於任意的二元組\((i,j)\)\(x_i \oplus x_j = a_{i+1} \oplus a_{i+2} \oplus ... \oplus a_j\)\(a\)為原數組,\(i\leq j(i\geq 0)\)

那麽就可以將問題轉換為求二元組\((i,j)\),使得\(x_i \oplus x_j\)最大 ,\(x_i \oplus x_j\)

即為\(lmax[i]\)

對於\(rmax[i]\)也是同理。只需要反過來求即可。

那麽如何求解最大的\(x_i \oplus x_j\)

使用字典樹,每次往裏面先插入一個二進制數,然後再查找與其對應位相反的數即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 6
#define SIZE 3

int s[SIZE+1];
int a[MAXN];
int Prefix[MAXN];
int Sufix[MAXN];
int lmax[MAXN];
int rmax[MAXN];
int N;

int trie[MAXN<<5][2];
int tot = 1;
inline void make_string(int x){
    for(register int i=SIZE;i>0;--i){
        s[i] = x&1;
        x>>=1;
    }
}
inline int insert(){
    int _next = 1;
    for(register int i=1;i<=SIZE;++i){
        int c = s[i];
        if(trie[_next][c])_next = trie[_next][c];
        else{
            trie[_next][c] = ++tot;
            _next = tot;
        }
    }
    int sum = 0;
    _next = 1;
    for(register int i=1;i<=SIZE;++i){
        int c = s[i]^1;
        if(trie[_next][c]){
            sum = (sum<<1) + 1;
            _next = trie[_next][c];
        }
        else{
            sum<<=1;
            _next = trie[_next][c^1];
        }
    }
    return sum;
}
int main(){

    scanf("%d",&N);int NN  = N;
    for(register int i=1;i<=N;++i){
        scanf("%d",&a[i]);
    }

    Prefix[0] = 0;
    Sufix[N+1] = 0;
    for(register int i=1;i<=N;++i){
        Prefix[i] = a[i]^Prefix[i-1];
    }
    for(register int i=N;i>0;--i){
        Sufix[i] = a[i]^Sufix[i+1];
    }

    tot = 1;
    for(register int i=0;i<N;++i){
        make_string(Prefix[i]);
        lmax[i] = std::max(insert(),lmax[i-1]); 
    }

    tot = 1;
    std::memset(trie,0,sizeof(trie));
    for(register int i=N+1;i>0;--i){
        make_string(Sufix[i]);
        rmax[i] = std::max(insert(),rmax[i+1]);
    }

    int maxx = 0;
    for(register int i=1;i<NN;++i){
        if(lmax[i]+rmax[i+1]>maxx)maxx = lmax[i]+rmax[i+1];
    }

    printf("%d",maxx);
    return 0;
}

[bzoj4260]Codechef REBXOR