zoukankan      html  css  js  c++  java
  • 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
    ", ans);
    }
    View Code
  • 相关阅读:
    POJ 3071 概率DP
    BZOJ 2427 /HAOI 2010 软件安装 tarjan缩点+树形DP
    POJ 1155 树形DP
    POJ 3252 组合数学?
    POJ 3641 快速幂
    POJ 3180 Tarjan
    POJ 3185 DFS
    POJ 3260 DP
    POJ 2392 DP
    99. Recover Binary Search Tree
  • 原文地址:https://www.cnblogs.com/Sakits/p/8432400.html
Copyright © 2011-2022 走看看