1. 程式人生 > >bzoj 4260 REBXOR —— Trie樹

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; }