bzoj 4260 REBXOR —— Trie树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4260
用 Trie 树可以找出前缀异或的最大值和后缀异或的最大值,拼起来即可;
注意要先加入一个0,表示区间左端点在 0 或右端点在 n+1;
竟然1A了!感动。
——然后发现3个月前做过!!!... https://www.cnblogs.com/Zinn/p/9301536.html
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int const xn=4e5+5,mx=30; int n,cnt,a[xn],pr[xn],sc[xn],c[xn*mx][2],bin[mx+5]; int rd() { int ret=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();} while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar(); return f?ret:-ret; } void init() { bin[0]=1; for(int i=1;i<=mx;i++)bin[i]=bin[i-1]*2; } void add(int x) { int nw=0; for(int i=mx;i>=0;i--) { bool d=(x&bin[i]); if(!c[nw][d])c[nw][d]=++cnt; nw=c[nw][d]; } } int query(int x) { int nw=0,ret=0; for(int i=mx;i>=0;i--) { bool d=!(x&bin[i]); if(c[nw][d])nw=c[nw][d],ret+=bin[i]; else nw=c[nw][!d]; } return ret; } int main() { n=rd(); init(); add(0);// for(int i=1,x,s=0;i<=n;i++) { x=rd(); a[i]=x; s^=x; pr[i]=max(pr[i-1],query(s)); add(s); } cnt=0; memset(c,0,sizeof c); add(0); for(int i=n,s=0;i;i--) { s^=a[i]; sc[i]=max(sc[i+1],query(s)); add(s); } int ans=0; for(int i=1;i<n;i++)ans=max(ans,pr[i]+sc[i+1]); printf("%d\n",ans); return 0; }