我是靠谱客的博主 朴素黑猫,最近开发中收集的这篇文章主要介绍BZOJ 4260: Codechef REBXOR 【Trie树贪心求区间异或和最值】,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题目传送门

题目分析:

f [ i ] f[i] f[i]表示 [ 1 , i ] [1,i] [1,i]中区间异或和的最大值 , g [ i ] g[i] g[i]表示 [ i , n ] [i,n] [i,n]中区间异或和的最大值
(一个前缀一个后缀)
那么答案就是 m a x { f [ i ] + g [ i + 1 ] } max{f[i]+g[i+1]} max{f[i]+g[i+1]}
考虑如何求 f f f,记 s [ i ] s[i] s[i]表示 [ 1 , i ] [1,i] [1,i]的异或和:
f [ i ] = m a x ( f [ i − 1 ] , s [ i ]   x o r   s [ j ] ) , j ∈ [ 0 , i − 1 ] f[i]=max(f[i-1],s[i]~xor~s[j]),jin[0,i-1] f[i]=max(f[i1],s[i] xor s[j]),j[0,i1]
要求后者的最值,只需要把前面的每个 s [ j ] s[j] s[j]拆成二进制位插入Trie树中,用 s [ i ] s[i] s[i]进去从高位到低位贪心,看是否有与当前位相反的数存在,存在就加入贡献,往那边走;不存在就往另一边走即可。(贪心是因为 2 n > 2 n − 1 + ⋯ + 2 0 2^n>2^{n-1}+dots+2^0 2n>2n1++20

最开始插入一个0,这样代码会好写很多。
Code:

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define maxn 400005
using namespace std;
inline void read(int &a){
    char c;while(!isdigit(c=getchar()));
    for(a=c-'0';isdigit(c=getchar());a=a*10+c-'0');
}
int n,a[maxn],s[maxn],f[maxn],g[maxn],ans;
int ch[maxn*30][2],tot;
void insert(int x){
    int r=0,v;
    for(int i=30;i>=0;i--,r=ch[r][v]) if(!ch[r][v=(x>>i&1)]) ch[r][v]=++tot;
}
int find(int x){
    int ret=0,r=0,v;
    for(int i=30;i>=0;i--,r=ch[r][v])
        if(ch[r][v=!(x>>i&1)]) ret+=1<<i;
        else if(ch[r][!v]) v=!v;
    return ret;
}
int main()
{
    read(n);
    for(int i=1;i<=n;i++) read(a[i]);
    insert(0);
    for(int i=1;i<=n;i++) s[i]=s[i-1]^a[i],f[i]=max(f[i-1],find(s[i])),insert(s[i]);
    memset(ch,0,sizeof ch);
    insert(0);
    for(int i=n;i>=1;i--) s[i]=s[i+1]^a[i],g[i]=max(g[i+1],find(s[i])),insert(s[i]);
    for(int i=1;i<n;i++) ans=max(ans,f[i]+g[i+1]);
    printf("%d",ans);
}

最后

以上就是朴素黑猫为你收集整理的BZOJ 4260: Codechef REBXOR 【Trie树贪心求区间异或和最值】的全部内容,希望文章能够帮你解决BZOJ 4260: Codechef REBXOR 【Trie树贪心求区间异或和最值】所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(31)

评论列表共有 0 条评论

立即
投稿
返回
顶部