字符串训练****

例题二:

https://loj.ac/problem/10051

题目描述:

在一个有 N个元素的序列 A 中,找出 下面式子的最大值

(A[L1]^A[L1+1]^^^^^^A[R1-1]^A[R1])+(A[L2]^A[L2+1]^^^^^^A[R2-1]^A[R2])的最大值

且要满足:1<=L1<=R1<L2<=R2<=N,N<=4e5,Ai<=1e9;

分析:肯定看到这题目描述想什么狗屁字符串,应该乱搞可以过の

但当你仔细想想乱搞是搞不出来的.....emmm

首先肯定能够想到和前缀异或有关

又是一个最值问题????dp

然后发现式子中间是有断点的

假如知道了断点前的最大值和断点后的最大值**

加起来O(n)线性扫一遍不就知道答案了吗?

pre[i]+suf[i+1];

现在主要就是求pre[i],suf[i]同理

现在就要利用前面说的前缀异或

设sum[i]=A[1]^A[2]^A[3]^^^^^^A[i];

pre[x]=max(sum[i]^sum[j])其中1<=i<=j<x

问题转化为

要求一个序列中[1,x]任意两个异或的最大值[板子题]

solution:

二进制拆分,放入一个Trie中,从最高位开始,每次选与它相反的(0--->1||1--->0),如果没得选就直接向下走

同理suf

code:

#include <iostream>
using namespace std;
int n,a[5000000],now,trie[50000000][3],tot,l[5000000],r[5000000],ans;
int insert(int x)
{
    int u(0);
    for (int i=30;i>=0;i--)
    {
        int ch=(x>>i)&1;
        if (!trie[u][ch])trie[u][ch]=++tot;
        u=trie[u][ch];
    }
}
int query(int x)
{
    int u(0),an(0);
    for (int i=30;i>=0;i--)
    {
        int ch=(x>>i)&1;
        if (trie[u][!ch])u=trie[u][!ch],an+=1<<i;
        else u=trie[u][ch];
    }
    return an;
}
int clear()
{
    for (int i=0;i<=tot;i++)
        for (int j=0;j<=1;j++)
            trie[i][j]=0;
    tot=0;
    now=0;
}
int main()
{
    cin>>n;
    insert(0);
    for (int i=1;i<=n;i++)
        cin>>a[i],now^=a[i],insert(now),l[i]=max(l[i-1],query(now));
    clear();
    insert(0);
    for (int i=n;i>=1;i--)
        now^=a[i],insert(now),r[i]=max(r[i+1],query(now));
    for (int i=1;i<n;i++)
        ans=max(ans,l[i]+r[i+1]);
    cout<<ans<<endl;
    return 0;
} 
01-14 07:59