[bzoj4260]Codechef REBXOR
阿新 • • 發佈:2018-08-17
一個 分享 string span efi 數據 ring 需要 hint 中的最大異或值,\(rmax[i]\)為原數組\([i,N]\)的最大異或值。
即為\(lmax[i]\)。
傳送門
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]\)
則我們只需要求出最大的\(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\)
對於\(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