图片说明
思路:
一边插入前缀异或值,一边查询之前插入的哪个数可以与当前数组成最大异或值,这样就变成了两个异或最大值问题了,不过还要求一下区间,对于插入的每个数,用一个数字记录一下他所在的地方,为什么这样是正确的呢,因为一个数异或自己等于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;
}