bzoj4260 求两个不相交的区间各自异或后相加的最大值。

题:http://www.lydsy.com/JudgeOnline/problem.php?id=4260

题意:如标题;

分析:利用前缀异或思想,设dp【i】为前 i 位任意区间异或的最大值,这个的求法就直接把前缀和数组边插入边查询,因为查询是查询x与已插入的数进行异或后能达到的最大值,而俩个前缀和异或就是一段区间

   然后根据dp【i】的求法用后缀异或和来遍历最优值

#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int M=4e5+5;
int dp[M],suf[M],pre[M],a[M];
struct TRIE{
    int trie[M*32][2],val[M*32];
    int tot;
    void init(){
        tot=0;
        memset(trie,0,sizeof(trie));
    }
    void Insert(int x){
        int now=0;
        for(int i=31;i>=0;i--){
            int id=(x>>i)&1;
            if(!trie[now][id])
                trie[now][id]=++tot;
            now=trie[now][id];
        }
        val[now]=x;
    }
    int query(int x){
        int now=0;
        for(int i=31;i>=0;i--){
            int id=(x>>i)&1;
            if(trie[now][id^1])
                now=trie[now][id^1];
            else
                now=trie[now][id];
        }
        return val[now]^x;
    }
}Trie;
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    pre[0]=suf[n+1]=0;
    for(int i=1;i<=n;i++)
        pre[i]=pre[i-1]^a[i];
    Trie.init();
    Trie.Insert(pre[0]);
    dp[0]=0;
    for(int i=1;i<=n;i++){
        dp[i]=max(dp[i-1],Trie.query(pre[i]));
        Trie.Insert(pre[i]);
    }
    for(int i=n;i>=1;i--)
        suf[i]=suf[i-1]^a[i];
    Trie.init();
    Trie.Insert(suf[n+1]);
    int ans=0;
    for(int i=n;i>=1;i--){
        ans=max(ans,dp[i-1]+Trie.query(suf[i]));
        Trie.Insert(suf[i]);
    }
    printf("%d\n",ans);
    return 0;
}
View Code

 

posted @ 2020-03-10 17:25  starve_to_death  阅读(148)  评论(0编辑  收藏  举报