bzoj 4260: Codechef REBXOR

来源:互联网 发布:网络阅卷答题卡 编辑:程序博客网 时间:2024/05/16 19:05

题意:

求两段异或和的和最大。

题解:

可持久化trie。我之前那篇写了。bzoj 2741
于是预处理两个东西,一个是前缀中的一段异或最大值,一个是后缀的最大值。
然后枚举下就好了。
贼慢,卡时过,可能是模板太菜了。
code:

#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#define LL long longconst int N=400005;using namespace std;struct trnode{    int c,a[2];}tr[35*N];int root[N],tot=0;LL read(){    LL x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}void add(int &x,int froot,LL k,int num){    x=++tot;    tr[x]=tr[froot];tr[x].c++;    if(num==-1) return;    LL c=(k&(1LL<<num));    c=(c!=0);    add(tr[x].a[c],tr[froot].a[c],k,num-1);}LL solve(int lroot,int rroot,LL k,int num){    if(num==-1) return 0;    LL c=(k&(1LL<<num));    c=(c!=0);c^=1;    int lrc=tr[tr[lroot].a[c]].c,rrc=tr[tr[rroot].a[c]].c;    if(lrc==rrc) c^=1;    return (c<<num)+solve(tr[lroot].a[c],tr[rroot].a[c],k,num-1);}int n;LL a[N],sum1[N],sum2[N];int main(){    n=read();a[0]=0;    add(root[1],root[0],0,33);    for(int i=1;i<=n;i++)    {        a[i+1]=read();        a[i+1]^=a[i];        add(root[i+1],root[i],a[i+1],33);    }    sum1[0]=-1;sum2[n+2]=-1;    for(int i=2;i<=n+1;i++) sum1[i]=max(sum1[i-1],solve(root[0],root[i],a[i],33)^a[i]);    for(int i=n+1;i>=2;i--) sum2[i]=max(sum2[i+1],solve(root[i-2],root[n+1],a[i],33)^a[i]);    LL ans=-1;    for(int i=2;i<=n;i++) ans=max(ans,sum1[i]+sum2[i+1]);    printf("%lld",ans);}
原创粉丝点击