思路:
一边插入前缀异或值,一边查询之前插入的哪个数可以与当前数组成最大异或值,这样就变成了两个异或最大值问题了,不过还要求一下区间,对于插入的每个数,用一个数字记录一下他所在的地方,为什么这样是正确的呢,因为一个数异或自己等于0,前缀异或值存的是[1,i]的异或和,我们在[i,i]再找一个j与他组成最大异或值,那么求的就是[j,i]的最大值[1,j - 1]异或了两次就是0了。
有点细节需要注意,比如要先插入一个0,不然1 2 4 8就hack了
代码:
#include<iostream> #include<vector> #include<cstring> #include<algorithm> using namespace std; const int maxn = 2e7 + 10; int trie[maxn][2],tot; int now[maxn]; int ans = -1,l,r,temp,n; void insert(int x,int id){ int p = 0; for(int i = 30; i >= 0; i--){ int c = (x >> i) & 1; if(!trie[p][c])trie[p][c] = ++ tot; p = trie[p][c]; } now[p] = id; } void query(int x,int cur){ int res = 0; int p = 0; for(int i = 30; i >= 0; i--){ int c = (x >> i) & 1; if(trie[p][c ^ 1])res |= (1 << i),p = trie[p][c ^ 1]; else p = trie[p][c]; } if(res > ans)ans = res,l = now[p] + 1,r = cur; } void solved(){ cin>>n; insert(0,0); for(int i = 1; i <= n; i++){ int x;cin>>x;temp = temp ^ x; query(temp,i); insert(temp,i); } cout<<ans<<" "<<l<<" "<<r<<endl; } int main(){ solved(); return 0; }