4260: Codechef REBXOR
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1653 Solved: 713
[ Submit][ Status][ Discuss]
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。
Source
这道题,嗯……刷完还是挺爽的,前面因为一些奇怪的原因被卡了空间(~_~|||)
好了,让我们来讲一讲这题的思路。
首先,这里提醒一下大家,凡是和XOR有关的80%是要用到trie,嗯~ o(* ̄▽ ̄*)o,没错,就是这样。
这一题要满足
我们可以把它分开来看,分别求出加号两边的最大值(最大前缀+最大后缀)然后就可以了!!
等等,忘记说嘴重要的部分了,就是求最大异或和。我们可以先用x[i]表示A[1]^A[2]^...^A[i-1]^A[i]。(注:“^”在c++中是异或运算的符号)
还有一个性质A[l]^A[l+1]^...^A[r-1]^A[r]=x[l-1]^x[r]。嗯~ o(* ̄▽ ̄*)o。
先做前缀最大值吧,假设为l[i],那么l[i]=max(x[i]^x[j])(j<i)。
那么后缀最大值(r[i])同理。
如果还没懂得话可以看我的代码理解一下。
出来吧,我的代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 400005;
int ch[N<<5][2],sum,tot,cnt[N<<5],A[N],n,k,l[N],r[N],ans;//注意ch开空间要开多32倍
void clear(){
memset(ch,0,sizeof(ch));
tot=0;sum=0;
}
void insert(int x){
int p=0;
for(int i=(1<<30);i;i>>=1){
int c=(i&x)? 1:0;
if(!ch[p][c]) ch[p][c]=++tot;
p=ch[p][c];
}
cnt[p]++;//就是这个东西(万恶之源),害的我GG了那么多次,而且还没啥用
}
int find(int x){
int p=0,ret=0;
for(int i=(1<<30);i;i>>=1){
int c=(i&x)? 0:1;
if(ch[p][c]){
ret+=i;
p=ch[p][c];
}else p=ch[p][!c];
}
return ret;
}
int main(){
ios::sync_with_stdio(false);//关同步,飞一般的感觉。
cin>>n;
for(int i=1;i<=n;i++){
cin>>A[i];
sum^=A[i];//前缀和
insert(sum);
l[i]=max(l[i-1],find(sum));//l[i]为A[l]~A[r}的最大值
}
clear();
for(int i=n;i>=1;i--){
sum^=A[i];//后缀和
insert(sum);
r[i]=max(r[i+1],find(sum));//l[i]为A[l]~A[r}的最大值
}
for(int i=1;i<n;i++){
ans=max(ans,l[i]+r[i+1]); //合并
}
cout<<ans;
return 0;
}
其实还是挺短的,嗯~ o(* ̄▽ ̄*)o
祝各位AC快乐!!