传送cf题目
传送牛客网题目
看了半个多小时的题解才搞明白,一下题解为自己的心得
参考博客(这两个讲的很详细):
参考一
参考二

题意:有一个长度有n的整数序列,你要在这个序列中选择一个前缀和后缀,前后缀不想交,前后缀任何一方都可以为空,问你前缀异或值与后缀异或值的异或最大是多少?
比如 一组数 1 2 3 4 5 6 你可以选择前缀为1 2,前缀异或和为3 选择后缀为4 5 6,后缀异或和为7
(前缀异或和)与(后缀异或和)异或值为4,但此时4并不是最大情况,求出最大情况

思路:
首先讲个小例题:

给一个数 a,还有一堆数,怎么在这一堆数中找出一个数 b,a 和 b 的异或值最大?

最暴力的方法无疑是(老办法) 枚举,枚举每一个b,但这样肯定不行(不然我写这个博客干什么) ,想想计算机的本质是啥?对,二进制。我们把a与这堆数转化成二进制,把后面这堆数装进一个字典树,当然要从最高位装,比如这堆数是123456,如图这堆数是123456根据异或规则不同为一,所以我们要使a与b异或最大,就要让b尽可能与a不同,a已经给定,b已经形成字典树,我们就从字典树root开始,尽量找出于a当前位置不同的数,直到找到最低位为止,那么这样找到的b满足条件。

回到这个题:
首先这些n个数组成一个区间w,w的全部异或结果是定值K,所以问题可以改成在区间w中取连续一段区间m,m的异或结果为X,m的前部分就成为区间w的前缀,后半部分就是区间w的后缀。
我们知道相同的数异或为零,那么X与K异或,重复的那部分区间异或后为零,就相当于是我们题目所求的
,所以就是求什么情况下X xor K最大。
发现现在的情况和一开始讲的例题很像了吧,我们假设有个Y,Y与K的每一个二进制相异,我们就要让X尽可能接近Y。
怎么实现呢?也是建一个字典树,将f[i]放进去(f[i]=a[1] ^ a[2] ^ a[3] ^ ...^ a[i]),那么f[i]^f[j]=a[i+1] ^ a[i+2] ^ ... ^aj可以表示i+1到j这段区间的异或值。
我们枚举区间m的结尾,每次用一个f[i]去匹配一个f[k],使得f[k]^f[i]的值在高位上尽可能去接近Y,这样就相当于选出区间[k+1,i]de异或值作为X,每次在[1,i]区间内匹配出来一个最佳区间后,不断更新答案。
看懂了吗?这些神奇的操作,巧妙利用字典树(工具人石锤)来匹配。
(太晚了就不重新打代码了,借用下参考二的代码)

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

typedef long long LL;
const int N=100006;

LL A[N], ans, cur, New;
int n;

struct Trie_Tree
{
    struct node
    {
        int next[2];
        void init()
        {
            next[0]=next[1]=-1;
        }
    } T[64*N];
    int tot;

    void Insert(LL val)
    {
        for(int i=63, u=0; i>=0; i--)
        {
            int id=(((1LL)<<i)&(val))!=0;
            if(T[u].next[id]==-1)
            {
                T[tot].init();
                T[u].next[id]=tot++;
            }
            u=T[u].next[id];
        }
    }

    LL Find(LL val)
    {
        LL res=0;
        for(int i=63, u=0; i>=0; i--)
        {
            int id=(((1LL)<<i)&(val))==0;
            if(T[u].next[id]==-1) id^=1;
            res=res*2LL+(LL)id;
            u=T[u].next[id];
        }
        return res;
    }
} tree;

int main()
{
    scanf("%d", &n);
    cur=0, New=0;
    for(int i=0; i<n; i++) scanf("%I64d", &A[i]), cur^=A[i];
    tree.T[0].init(), tree.tot=1, ans=cur;
    tree.Insert(0LL);
    for(int i=0; i<n; i++)
    {
        New^=A[i], cur^=A[i];
        tree.Insert(New);
        LL temp=tree.Find(cur);
        ans=max(ans, temp^cur);
    }
    printf("%I64d\n", ans);
    return 0;
}