概述
链接:HYSBZ - 4260 Codechef REBXOR
题意:
其中
2
≤
N
≤
4
∗
1
0
5
2le Nle4*10^5
2≤N≤4∗105,
0
≤
A
i
≤
1
0
9
0le A_ile 10^9
0≤Ai≤109
分析:
由于异或的性质: a ⊕ a = 0 aoplus a=0 a⊕a=0, 0 ⊕ a = a 0oplus a=a 0⊕a=a
所以 连续区间的异或和 a [ L ] ⊕ a [ L + 1 ] ⊕ ⋯ ⊕ a [ R ] a[L]oplus a[L+1]opluscdotsoplus a[R] a[L]⊕a[L+1]⊕⋯⊕a[R]可以用前缀异或和(或后缀)的形式表示。
如前缀异或和: p r e [ i ] pre[i] pre[i],表示 x o r j = 1 i a [ j ] xor_{j=1}^{i}a[j] xorj=1ia[j]
那么有 a [ L ] ⊕ a [ L + 1 ] ⊕ ⋯ ⊕ a [ R ] = p r e [ R ] ⊕ p r e [ L − 1 ] a[L]oplus a[L+1]opluscdotsoplus a[R]=pre[R]oplus pre[L-1] a[L]⊕a[L+1]⊕⋯⊕a[R]=pre[R]⊕pre[L−1]
其中 p r e [ R ] = x o r j = 1 R a [ j ] pre[R]=xor_{j=1}^{R}a[j] pre[R]=xorj=1Ra[j] 和 p r e [ L − 1 ] = x o r j = 1 L − 1 a [ j ] pre[L-1]=xor_{j=1}^{L-1}a[j] pre[L−1]=xorj=1L−1a[j] 相同的部分(a[1]~a[L-1])异或得到0,
而剩下的部分(a[L] ~ a[R])与0异或,还是本身。
对于该题,要求两段不相交的异或区间和相加的最大结果,可以先处理左边的一段,我们要求得这样一个数组 d p [ i ] dp[i] dp[i]:表示开头到 i i i为止(即 1 1 1 ~ i i i)的最大区间异或和。
我们要先求得 p r e _ a n s [ i ] pre_ans[i] pre_ans[i]:表示以 i i i结尾( i i i为右端点 R R R)的最大区间异或和,求解很简单,根据开始说的区间异或和求法,我们只需要每次在01字典树中找到与 p r e [ i ] pre[i] pre[i]异或的最大值,即为 p r e _ a n s [ i ] pre_ans[i] pre_ans[i],然后把 p r e [ i ] pre[i] pre[i]放入字典树即可。
那么就有 d p [ i ] = max ( d p [ i − 1 ] , p r e _ a n s [ i ] ) dp[i]=max(dp[i-1],pre_ans[i]) dp[i]=max(dp[i−1],pre_ans[i])
然后再求右边一段,同理从后向前遍历求得 p o s t _ a n s [ i ] post_ans[i] post_ans[i],
那么有最终答案 a n s = max ( a n s , p o s t _ a n s [ i ] + d p [ i − 1 ] ) ans=max(ans,post_ans[i]+dp[i-1]) ans=max(ans,post_ans[i]+dp[i−1])
以下代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=4e5+50;
const int max_base=31;
int n,a[maxn],pre[maxn],post[maxn];
int ch[31*maxn][2],val[31*maxn],tot;
void init()
{
tot=1;
ch[0][0]=ch[0][1]=0;
val[0]=0;
}
void ins(int x)
{
int u=0;
for(int i=max_base;i>=0;i--)
{
int c=(x>>i)&1;
if(!ch[u][c])
{
ch[tot][0]=ch[tot][1]=0;
val[tot]=0;
ch[u][c]=tot++;
}
u=ch[u][c];
}
val[u]=x;
}
int query_max(int x)
{
int u=0;
for(int i=max_base;i>=0;i--)
{
int c=(x>>i)&1;
if(ch[u][c^1])
u=ch[u][c^1];
else
u=ch[u][c];
}
return x^val[u];
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
pre[0]=0;
for(int i=1;i<=n;i++)
pre[i]=pre[i-1]^a[i];
post[n+1]=0;
for(int i=n;i>=1;i--)
post[i]=post[i+1]^a[i];
int dp[maxn],ans;
init();
dp[0]=0;
ins(pre[0]);
for(int i=1;i<=n;i++)
{
dp[i]=max(dp[i-1],query_max(pre[i]));
ins(pre[i]);
}
init();
ans=0;
ins(post[n+1]);
for(int i=n;i>=2;i--)
{
ans=max(ans,query_max(post[i])+dp[i-1]);
ins(post[i]);
}
printf("%dn",ans);
return 0;
}
最后
以上就是风趣大树为你收集整理的HYSBZ - 4260 Codechef REBXOR(前缀和求区间连续异或和,01字典树)的全部内容,希望文章能够帮你解决HYSBZ - 4260 Codechef REBXOR(前缀和求区间连续异或和,01字典树)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复