DestinHistoire

 

BZOJ-4260 Codechef REBXOR(trie)

题目描述

  给定一个有 \(n(2\leq n\leq 4\times 10^5)\) 个元素的数组 \(a\),下标从 \(1\) 开始,求下式的最大值:

\[(a[L_1]\oplus a[L_1+1]\oplus\cdots\oplus a[R_1])+(a[L_2]\oplus a[L_2+1]\oplus\cdots\oplus a[R_2]) \]

  其中 \(1\leq L_1\leq R_1\leq L_2\leq R_2\leq n\)\(\oplus\) 表示异或运算。

分析

  设 \(l[i]\)\(1\leq L\leq R\leq i\) 的最大的 \(a[L]\oplus a[L+1]\oplus\cdots \oplus a[R]\)\(r[i]\)\(i\leq L\leq R\leq n\) 的最大的 \(a[L]\oplus a[L+1]\oplus\cdots \oplus a[R]\),则答案为 \(l[i]+r[i+1]\)

  设 \(presum[i]\)\(a[0]\oplus a[1]\oplus a[2]\oplus \cdots\oplus a[i](a[0]=0)\),则 \(l[i]=\max(presum[i]\oplus presum[j])(0\leq j<i)\),把 \(presum\) 数组插入到第一棵 \(\text{trie}\) 中,尽量走相反的字符指针即可求出 \(l[i]\)。同理,设 \(sufsum[i]=a[n+1]\oplus a[n-1]\oplus\cdots\oplus a[i](a[n+1]=0)\),则 \(r[i]=\max(sufsum[i]\oplus sufsum[j])(i<j\leq n+1)\),把 \(sufsum\) 数组插入到第二棵 \(\text{trie}\) 中,尽量走相反的字符指针即可求出 \(r[i]\)

代码

#include<bits/stdc++.h>
using namespace std;
const int N=4e5+10;
int l[N],r[N],a[N];
int presum[N],sufsum[N];
struct Trie
{
    int trie[N*30][2],tot=1;
    void insert(int val)
    {
        int p=1;
        for(int i=30;i>=0;i--)
        {
            int num=(val>>i)&1;
            if(trie[p][num]==0)
                trie[p][num]=++tot;
            p=trie[p][num];
        }
    }
    int query(int val)
    {
        int p=1;
        long long ans=0;
        for(int i=30;i>=0;i--)
        {
            int num=(val>>i)&1;
            if(trie[p][!num])
            {
                ans=ans+(1<<i);
                p=trie[p][!num];
            }
            else
                p=trie[p][num];
        }
        return ans;
    }
}A,B;
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    presum[0]=0;
    A.insert(presum[0]);
    for(int i=1;i<=n;i++)
    {
        presum[i]=presum[i-1]^a[i];
        A.insert(presum[i]);
        l[i]=max(l[i-1],A.query(presum[i]));
    }
    B.insert(0);
    sufsum[n+1]=0;
    for(int i=n;i>=1;i--)
    {
        sufsum[i]=sufsum[i+1]^a[i];
        B.insert(sufsum[i]);
        r[i]=max(r[i+1],B.query(sufsum[i]));
    }
    int ans=0;
    for(int i=1;i<=n-1;i++)
        ans=max(ans,l[i]+r[i+1]);
    cout<<ans<<endl;
    return 0;
}

posted on 2020-11-24 00:19  DestinHistoire  阅读(64)  评论(0)    收藏  举报

导航