预处理前后缀异或和,用trie得到前后缀最大答案,枚举中间点把左右两边加起来就是当前中间点的最大答案了...这个操作没见过,比较有意思,记录一下
#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<algorithm> #define ll long long using namespace std; const int maxn=500010, inf=1e9; struct poi{int nxt[2];}tree[maxn*30]; int n, ans, tott; int a[maxn], suml[maxn], sumr[maxn], ansl[maxn], ansr[maxn]; inline void read(int &k) { int f=1; k=0; char c=getchar(); while(c<‘0‘ || c>‘9‘) c==‘-‘&&(f=-1), c=getchar(); while(c<=‘9‘ && c>=‘0‘) k=k*10+c-‘0‘, c=getchar(); k*=f; } inline int getans(int x) { int ans=0, now=0; for(int i=30, y;~i;i--) if(tree[now].nxt[(y=(x&(1<<i))!=0)^1]) ans+=(1<<i), now=tree[now].nxt[y^1]; else now=tree[now].nxt[y]; return ans; } inline void insert(int x) { int now=0; for(int i=30, y;~i;i--) if(tree[now].nxt[y=(x&(1<<i))!=0]) now=tree[now].nxt[y]; else tree[now].nxt[y]=++tott, now=tott; } int main() { read(n); for(int i=1;i<=n;i++) read(a[i]), suml[i]=suml[i-1]^a[i]; for(int i=n;i;i--) sumr[i]=sumr[i+1]^a[i]; insert(0); for(int i=1;i<=n;i++) ansl[i]=max(ansl[i-1], getans(suml[i])), insert(suml[i]); memset(tree, 0, sizeof(tree)); insert(0); for(int i=n;i;i--) ansr[i]=max(ansr[i+1], getans(sumr[i])), insert(sumr[i]); for(int i=1;i<=n;i++) ans=max(ans, ansl[i]+ansr[i]); printf("%d\n", ans); }