bzoj2134: 单选错位(trie)

Posted Sakits

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj2134: 单选错位(trie)相关的知识,希望对你有一定的参考价值。

  预处理前后缀异或和,用trie得到前后缀最大答案,枚举中间点把左右两边加起来就是当前中间点的最大答案了...这个操作没见过,比较有意思,记录一下

技术分享图片
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=500010, inf=1e9;
struct poi{int nxt[2];}tree[maxn*30];
int n, ans, tott;
int a[maxn], suml[maxn], sumr[maxn], ansl[maxn], ansr[maxn];
inline void read(int &k)
{
    int f=1; k=0; char c=getchar();
    while(c<0 || c>9) c==-&&(f=-1), c=getchar();
    while(c<=9 && c>=0) k=k*10+c-0, c=getchar();
    k*=f;    
} 
inline int getans(int x)
{
    int ans=0, now=0;
    for(int i=30, y;~i;i--)
    if(tree[now].nxt[(y=(x&(1<<i))!=0)^1])
    ans+=(1<<i), now=tree[now].nxt[y^1];
    else now=tree[now].nxt[y];
    return ans;
}
inline void insert(int x)
{
    int now=0;
    for(int i=30, y;~i;i--)
    if(tree[now].nxt[y=(x&(1<<i))!=0]) now=tree[now].nxt[y];
    else tree[now].nxt[y]=++tott, now=tott;
}
int main()
{
    read(n);
    for(int i=1;i<=n;i++) read(a[i]), suml[i]=suml[i-1]^a[i];
    for(int i=n;i;i--) sumr[i]=sumr[i+1]^a[i];
    insert(0);
    for(int i=1;i<=n;i++) ansl[i]=max(ansl[i-1], getans(suml[i])), insert(suml[i]);
    memset(tree, 0, sizeof(tree)); insert(0);
    for(int i=n;i;i--) ansr[i]=max(ansr[i+1], getans(sumr[i])), insert(sumr[i]);
    for(int i=1;i<=n;i++) ans=max(ans, ansl[i]+ansr[i]);
    printf("%d\n", ans);
}
View Code

 

以上是关于bzoj2134: 单选错位(trie)的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2134 单选错位

bzoj2134 单选错位

Bzoj2134:单选错位

BZOJ 2134 单选错位

BZOJ2134: 单选错位(期望乱搞)

BZOJ_2134_单选错位——期望DP