bzoj4260 求两个不相交的区间各自异或后相加的最大值。
题:http://www.lydsy.com/JudgeOnline/problem.php?id=4260
题意:如标题;
分析:利用前缀异或思想,设dp【i】为前 i 位任意区间异或的最大值,这个的求法就直接把前缀和数组边插入边查询,因为查询是查询x与已插入的数进行异或后能达到的最大值,而俩个前缀和异或就是一段区间
然后根据dp【i】的求法用后缀异或和来遍历最优值
#include<bits/stdc++.h> using namespace std; const int inf=0x3f3f3f3f; const int M=4e5+5; int dp[M],suf[M],pre[M],a[M]; struct TRIE{ int trie[M*32][2],val[M*32]; int tot; void init(){ tot=0; memset(trie,0,sizeof(trie)); } void Insert(int x){ int now=0; for(int i=31;i>=0;i--){ int id=(x>>i)&1; if(!trie[now][id]) trie[now][id]=++tot; now=trie[now][id]; } val[now]=x; } int query(int x){ int now=0; for(int i=31;i>=0;i--){ int id=(x>>i)&1; if(trie[now][id^1]) now=trie[now][id^1]; else now=trie[now][id]; } return val[now]^x; } }Trie; int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); pre[0]=suf[n+1]=0; for(int i=1;i<=n;i++) pre[i]=pre[i-1]^a[i]; Trie.init(); Trie.Insert(pre[0]); dp[0]=0; for(int i=1;i<=n;i++){ dp[i]=max(dp[i-1],Trie.query(pre[i])); Trie.Insert(pre[i]); } for(int i=n;i>=1;i--) suf[i]=suf[i-1]^a[i]; Trie.init(); Trie.Insert(suf[n+1]); int ans=0; for(int i=n;i>=1;i--){ ans=max(ans,dp[i-1]+Trie.query(suf[i])); Trie.Insert(suf[i]); } printf("%d\n",ans); return 0; }