By yts1999
可持久化Trie树
计算异或前缀和,一段区间的异或和就转化为两个数的异或和。
然后求出1-i的最大异或和f[i]、i-n的最大异或和g[i],在可持久化Trie树上贪心即可。
然后枚举中间的分隔位置,计算答案。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<algorithm> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define ll long long #define maxn 400005 #define maxm 15000005 #define inf 1<<29 using namespace std; int n,cnt,ans,mx; int sum[maxn],rt[maxn],f[maxn],g[maxn]; int sz[maxm],a[maxm][2]; inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void insert(int x,int &y,int val,int tmp) { y=++cnt;sz[y]=sz[x]+1; if (!tmp) return; a[y][0]=a[x][0];a[y][1]=a[x][1]; int t=val&tmp?1:0; insert(a[x][t],a[y][t],val,tmp>>1); } int query(int x,int y,int val,int tmp) { if (!tmp) return 0; int t=(val&tmp?1:0)^1; if (sz[a[y][t]]>sz[a[x][t]]) return query(a[x][t],a[y][t],val,tmp>>1)+tmp; else return query(a[x][t^1],a[y][t^1],val,tmp>>1); } int main() { n=read(); F(i,1,n) sum[i]=sum[i-1]^read(); insert(0,rt[0],0,inf); F(i,1,n) insert(rt[i-1],rt[i],sum[i],inf); F(i,1,n) { f[i]=query(0,rt[i-1],sum[i],inf); g[i]=query(rt[i-1],rt[n],sum[i-1],inf); } mx=f[1]; F(i,2,n) ans=max(ans,g[i]+mx),mx=max(mx,f[i]); printf("%d\n",ans); return 0; }