• Nikitosh 和异或


    https://loj.ac/problem/10051

    题目描述

      给出(N)个数的序列(A),要求求出两段连续的子序列(互不重叠),他们内的数异或后值的和最大。

    思路

      这道题其实是The XOR Largest Pair的进阶版,我们知道暴力枚举显然无法实现,所以就要用到一些优化。首先我们考虑如果选出一段连续子序列最大如何做。我们已知一个很显然的性质(xigoplus x=0)(0igoplus x=x),所以对于一段子序列我们可以用类似维护前缀和的方法,用(s[r]igoplus s[l-1])取出([l,r])这一段的异或值,因为前几个数可以异或为(0)。不过暴力枚举子序列的复杂度我们仍无法承受,但我们知道快速从一堆数中求出一对数异或值最大。所以这就等价于从(s[1..r-1])找出和(s[r])异或起来最大值,再取个(max)即可,我们也可用字典树维护。

      接下来就是两段不重叠的序列,我们知道这一定由两段([l1,r1])([l2,r2]),因此他们一定可以从一个端点分为两部分,所以我们只要正着做一遍,倒着做一遍,得到两个数组(l,r),那么答案就是(l[i]+r[i+1])中的最大值。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN=4e5+5;
    int ch[MAXN<<5][3],tot,a[MAXN],l[MAXN],r[MAXN];
    void insert(int x)
    {
        int u=1;
        for(int i=1<<30;i;i>>=1)
        {
            int num=(x&i)?1:0;
            if(!ch[u][num])ch[u][num]=++tot;
            u=ch[u][num];
        }
    }
    int find(int x)
    {
        int u=1,ans=0;
        for(int i=1<<30;i;i>>=1)
        {
            int num=(x&i)?0:1;
            if(ch[u][num])
            {
                ans+=i;
                u=ch[u][num];
            }
            else u=ch[u][!num];
        }
        return ans;
    }
    int main() 
    {
        int n,sum=0;
        scanf("%d",&n);
        tot=1;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            sum=sum^a[i];
            insert(sum);
            l[i]=max(l[i-1],find(sum));
        }
        memset(ch,0,sizeof(ch));
        sum=0;tot=1;
        for(int i=n;i>0;i--)
        {
            sum=sum^a[i];
            insert(sum);
            r[i]=max(r[i+1],find(sum));
        }
        int ans=0;
        for(int i=1;i<=n;i++)
            ans=max(ans,l[i]+r[i+1]);
        printf("%d",ans);
        return 0;
    }
    
  • 相关阅读:
    axios的使用/
    jQuery好玩的双向控制轮播
    vue的路由跳转方式/两种
    vfor的某些注意事项
    vue使用插件时不能撑满页面?
    swiper中的双向控制器不生效问题
    sass的安装及使用
    .net必懂题
    软件架构初读01
    EJB
  • 原文地址:https://www.cnblogs.com/fangbozhen/p/11788266.html
Copyright © 2020-2023  润新知