【bzoj4260】 Codechef REBXOR trie树
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。
题解:
其实很好想的,维护一个lmx[i]表示到1-i中最大的连续的xor和。
rmx[i]表示i-n重最大的连续的xor和,然后就是前缀和的形式
插入字典树,然后在字典树中找两个值的xor最大值。
就是找1的时候向0的方向找,0的时候向1的方向找。
很好理解吧。
1 #include<cstring> 2 #include<cmath> 3 #include<algorithm> 4 #include<iostream> 5 #include<cstdio> 6 #define N 400007 7 using namespace std; 8 9 int n,cnt=1; 10 int a[N],lmx[N],rmx[N]; 11 struct Node 12 { 13 int point[2]; 14 void init() 15 { 16 point[1]=point[0]=0; 17 } 18 }trie[400007*30]; 19 20 void insert(int x) 21 { 22 int now=1; 23 for (int i=31,t;i>=0;i--) 24 { 25 if (x&(1<<i)) t=1; 26 else t=0; 27 if (!trie[now].point[t]) trie[now].point[t]=++cnt; 28 now=trie[now].point[t]; 29 } 30 } 31 int calc(int x) 32 { 33 int now=1,ans=0; 34 for (int i=31,t;i>=0;i--) 35 { 36 if (x&(1<<i)) t=1; 37 else t=0; 38 if (trie[now].point[t^1]) 39 { 40 ans=ans+(1<<i); 41 now=trie[now].point[t^1]; 42 } 43 else now=trie[now].point[t]; 44 } 45 return ans; 46 } 47 int main() 48 { 49 scanf("%d",&n); 50 for (int i=1;i<=n;i++) 51 scanf("%d",&a[i]); 52 int x=0;insert(x); 53 for (int i=1;i<=n;i++) 54 { 55 x=x^a[i]; 56 insert(x); 57 lmx[i]=max(lmx[i-1],calc(x)); 58 } 59 60 cnt=1; 61 for (int i=0;i<400007*30;i++) trie[i].init(); 62 63 x=0;insert(x); 64 for (int i=n;i>=1;i--) 65 { 66 x=x^a[i]; 67 insert(x); 68 rmx[i]=max(rmx[i+1],calc(x)); 69 } 70 int ans=-1; 71 for (int i=2;i<=n;i++) 72 ans=max(ans,lmx[i-1]+rmx[i]); 73 printf("%d\n",ans); 74 }