码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj2134: 单选错位(trie)

时间:2018-02-08 20:23:57      阅读:196      评论:0      收藏:0      [点我收藏+]

标签:中间   pen   mem   分享   struct   size   gif   cst   line   

  预处理前后缀异或和,用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)

标签:中间   pen   mem   分享   struct   size   gif   cst   line   

原文地址:https://www.cnblogs.com/Sakits/p/8432400.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!