[bzoj4260]Codechef REBXOR

4260: Codechef REBXOR

Time Limit: 10 Sec   Memory Limit: 256 MB
Submit: 1653   Solved: 713
[ Submit][ Status][ Discuss]

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。

Source

[ Submit][ Status][ Discuss]



这道题,嗯……刷完还是挺爽的,前面因为一些奇怪的原因被卡了空间(~_~|||)


好了,让我们来讲一讲这题的思路。

首先,这里提醒一下大家,凡是和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快乐!!

猜你喜欢

转载自blog.csdn.net/qq_38944163/article/details/80996513