bzoj4260 REBXOR——Trie树

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4260

对于每个位置,求一个前缀最大值和后缀最大值;

也就是从1到 i 的异或和要找前面某处的一个异或和,异或一下就有了一段区间的异或和;

要最大化这个值,就是从前面所有异或和中找到恰好和这个值相反的,所以可以在前面所有异或和构建出的 Trie 树上查找;

学习了一下写 Trie 树的姿势!

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int const maxn=4e5+5;
int n,a[maxn],c[maxn*30][3],tot,f[maxn],g[maxn],ans;
void insert(int x)
{
    int nw=0;
    for(int i=(1<<30);i;i>>=1)
    {
        bool w=(x&i); //w可能不只是 0 或 1 !
        if(!c[nw][w])c[nw][w]=++tot;
        nw=c[nw][w];
    }
}
int query(int x)
{
    int nw=0,ret=0;
    for(int i=(1<<30);i;i>>=1)
    {
//        int w=(x&i); //w可能不只是 0 或 1 !
        bool w=(x&i); w=!w; 
        if(c[nw][w])ret+=i,nw=c[nw][w];
        else nw=c[nw][w^1];
    }
    return ret;
}
int main()
{
    scanf("%d",&n);
    insert(0); int nw=0;
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
    {
        nw^=a[i];
        f[i]=max(f[i-1],query(nw));
        insert(nw);
    }
    memset(c,0,sizeof c);
    tot=0; nw=0; insert(0);
    for(int i=n;i;i--)
    {
        nw^=a[i];
        g[i]=max(g[i+1],query(nw));
        insert(nw);
    }
    for(int i=1;i<=n;i++)ans=max(ans,f[i]+g[i+1]);//g[i+1] 
    printf("%d",ans);
    return 0;
}

 

posted @ 2018-07-12 19:43  Zinn  阅读(174)  评论(0编辑  收藏  举报