我是靠谱客的博主 称心枫叶,最近开发中收集的这篇文章主要介绍BZOJ 4260 Codechef REBXOR,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1.题链接

 

求两个不相交的区间各自异或后相加的最大值。n的范围1<=n<=4e5

 

首先我们知道

前 i 个数的异或和前 j 个数的异或相异或: pre[i]^pre[j] = a[i+1]^a[i+2]^……^a[j],(i<j)。异或的后缀和类似。

 

于是我们可以先求出异或的前缀 suf[i]和后缀和 fi[i]。dp[i]表示前 i个数中任意区间异或的最大值,可以依次求与 suf[i] 相异或结果的最大值,然后把 suf[i] 插入到 01字典树中。

 

这样对于每个suf[i] 他会和之前的 i-1 个异或前缀和的共有部分所抵消,也就相当于是求任意区间的异或结果的最大值了。这样求出了一个区间,同理可利用后缀和求出另一个区间。

 

怎么保证两个区间不相交呢?可以通过使前后两个区间一个为不包含第 i个数的前部分区间,一个是包含第 i 个数的后部分区间就可以了。

 

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a)) 
const int maxn=4e5+10;
int n,m,num[maxn*32],ch[maxn*32][2],tot;
int val[maxn*32],a[maxn],suf[maxn],fi[maxn],dp[maxn];
void init(){
	tot=1;
	ch[0][0]=ch[0][1]=0;
}
void insert(int x){
	int u=0;
	for(int i=32;i>=0;i--){
		int v=(x>>i)&1;
		if(!ch[u][v]){
			ch[tot][0]=ch[tot][1]=0;
			val[tot]=num[tot]=0;
			ch[u][v]=tot++;
		}
		u=ch[u][v];
		num[u]++;
	}
	val[u]=x;
}
int query(int x){
	int u=0;
	for(int i=32;i>=0;i--){
		int v=(x>>i)&1;
		if(ch[u][v^1]&&num[ch[u][v^1]]) u=ch[u][v^1];
		else u=ch[u][v];
	}
	return x^val[u];
}
int main(){
	int i,j;
	scanf("%d",&n);
	dp[0]=suf[0]=fi[n+1]=0;
	for(i=1;i<=n;i++){
		scanf("%d",&a[i]);
		suf[i]=suf[i-1]^a[i];
	}
	init();
	for(i=n;i>=1;i--)
		fi[i]=fi[i-1]^a[i];
	int ans=0;
	insert(suf[0]);
	for(i=1;i<=n;i++){
		dp[i]=max(dp[i-1],query(suf[i]));
		insert(suf[i]);
	}
	init();
	insert(fi[n+1]);
	for(i=n;i>=1;i--){
		ans=max(ans,dp[i-1]+query(fi[i]));
		insert(fi[i]);
	}
	printf("%dn",ans);
	return 0;
}

 

最后

以上就是称心枫叶为你收集整理的BZOJ 4260 Codechef REBXOR的全部内容,希望文章能够帮你解决BZOJ 4260 Codechef REBXOR所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(36)

评论列表共有 0 条评论

立即
投稿
返回
顶部