bzoj4260 REBXOR——Trie树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4260
对于每个位置,求一个前缀最大值和后缀最大值;
也就是从1到 i 的异或和要找前面某处的一个异或和,异或一下就有了一段区间的异或和;
要最大化这个值,就是从前面所有异或和中找到恰好和这个值相反的,所以可以在前面所有异或和构建出的 Trie 树上查找;
学习了一下写 Trie 树的姿势!
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int const maxn=4e5+5; int n,a[maxn],c[maxn*30][3],tot,f[maxn],g[maxn],ans; void insert(int x) { int nw=0; for(int i=(1<<30);i;i>>=1) { bool w=(x&i); //w可能不只是 0 或 1 ! if(!c[nw][w])c[nw][w]=++tot; nw=c[nw][w]; } } int query(int x) { int nw=0,ret=0; for(int i=(1<<30);i;i>>=1) { // int w=(x&i); //w可能不只是 0 或 1 ! bool w=(x&i); w=!w; if(c[nw][w])ret+=i,nw=c[nw][w]; else nw=c[nw][w^1]; } return ret; } int main() { scanf("%d",&n); insert(0); int nw=0; for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=n;i++) { nw^=a[i]; f[i]=max(f[i-1],query(nw)); insert(nw); } memset(c,0,sizeof c); tot=0; nw=0; insert(0); for(int i=n;i;i--) { nw^=a[i]; g[i]=max(g[i+1],query(nw)); insert(nw); } for(int i=1;i<=n;i++)ans=max(ans,f[i]+g[i+1]);//g[i+1] printf("%d",ans); return 0; }