bzoj4260: Codechef REBXOR

真是被毒瘤了。。。本机拍成SB过不去

一怒之下全改成LL过了

无话可说。。

做法就是前缀和后正反搞两次字典树找异或最大(这好像是套路然而yy也不是很难)

然后找前后不相交的区间相加最大就行了。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;

LL Bin[40];
void yu(){Bin[0]=1;for(int i=1;i<=37;i++)Bin[i]=Bin[i-1]*2;}
struct Trie
{
    LL w[2];
    void clean(){w[0]=w[1]=0;}
}tr[6100000];LL trlen;
void insert(LL d)
{
    LL now=0;
    for(LL i=35;i>=0;i--)
    {
        LL x=((d&Bin[i])>>i);
        if(tr[now].w[x]==0)
            tr[now].w[x]=++trlen, tr[trlen].clean();
        now=tr[now].w[x];
    }
}
LL findmax(LL d)
{
    LL now=0;LL ret=0;
    for(LL i=35;i>=0;i--)
    {
        LL x=((d&Bin[i])>>i);
        
        if(tr[now].w[x^1]!=0)
            ret+=Bin[i], now=tr[now].w[x^1];
            
        else if(tr[now].w[x]!=0)
            now=tr[now].w[x];
            
        else break;
    }
    return ret;    
}

LL a[410000];
LL lmx[410000],rmx[410000];
LL lmax[410000],rmax[410000];
int main()
{
    freopen("rebxor.in","r",stdin);
    freopen("rebxor.out","w",stdout);
    LL n;LL x;yu();
    scanf("%lld",&n);
    for(LL i=1;i<=n;i++)scanf("%lld",&a[i]);
    
    LL s;
    
    trlen=0;tr[trlen].clean();s=0;
    for(LL i=1;i<=n;i++)
    {
        s^=a[i];
        lmx[i]=max(s,findmax(s));
        insert(s);
    }
    trlen=0;tr[trlen].clean();s=0;
    for(LL i=n;i>=1;i--)
    {
        s^=a[i];
        rmx[i]=max(s,findmax(s));
        insert(s);
    }
    
    lmax[1]=lmx[1];for(LL i=2;i<=n;i++)lmax[i]=max(lmx[i],lmax[i-1]);
    rmax[n]=rmx[n];for(LL i=n-1;i>=1;i--)rmax[i]=max(rmx[i],rmax[i-1]);
    
    LL mmax=0;
    for(LL i=1;i<n;i++)
    {
        mmax=max(mmax,lmax[i]+rmax[i+1]);
    }
    printf("%lld\n",mmax);
    return 0;
}

 

posted @ 2018-04-19 12:54  AKCqhzdy  阅读(141)  评论(0编辑  收藏  举报