概述
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所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复