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; }
pain and happy in the cruel world.