我是靠谱客的博主 风趣大树,最近开发中收集的这篇文章主要介绍HYSBZ - 4260 Codechef REBXOR(前缀和求区间连续异或和,01字典树),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

链接:HYSBZ - 4260 Codechef REBXOR

题意:

在这里插入图片描述
其中 2 ≤ N ≤ 4 ∗ 1 0 5 2le Nle4*10^5 2N4105 0 ≤ A i ≤ 1 0 9 0le A_ile 10^9 0Ai109


分析:

由于异或的性质: a ⊕ a = 0 aoplus a=0 aa=0 0 ⊕ a = a 0oplus a=a 0a=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[L1]

其中 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[L1]=xorj=1L1a[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[i1],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[i1])



以下代码:

#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字典树)所遇到的程序开发问题。

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

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

评论列表共有 0 条评论

立即
投稿
返回
顶部