题意: 给定长度为的序列,求出连续的子序列中异或值的最大值以及子序列的首尾位置,如果有多个子序列最大值相同,则考虑最短的子序列,如果最短的仍有多个,则继续考虑末尾位置小的。
数据范围:

题解:
异或子序列的经典解决方案就是结合异或的特性,的异或值为
当前枚举到第个前缀时,可以在树中找到与当前前缀异或得到的最大前缀。
由于考虑子序列最短,所以每个前缀值都存储当前已经枚举的最大的索引即可。

代码:

#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;
int a[N];
int son[N * 22][2], idx;
int id[N * 22];
void insert(int num) {
    int p = 0;
    for(int i = 21; i >= 0; --i) {
        int u = a[num] >> i & 1;
        if(!son[p][u]) son[p][u] = ++idx;
        p = son[p][u];
    }
    id[p] = max(id[p], num);
}

int query(int x, int &f) {
    int p = 0, res = 0;
    for(int i = 21; i >= 0; --i) {
        int u = x >> i & 1;
        if(son[p][!u]) res = res * 2 + !u, p = son[p][!u];
        else res = res * 2 + u, p = son[p][u];
    }
    f = id[p];
    return res;
}

int main()
{
    int n; scanf("%d", &n);
    for(int i = 1; i <= n; ++i) scanf("%d", &a[i]), a[i] ^= a[i - 1];
    int ans = a[1], fir = 1, en = 1;
    for(int i = 1; i <= n; ++i) {
        insert(i);
        int f = -1;
        int t = query(a[i], f) ^ a[i];
        if(ans < t) {ans = t, fir = f + 1, en = i;}
    }
    printf("%d %d %d\n", ans, fir, en);
    return 0;
}