LOJ10051

13 篇文章 0 订阅
7 篇文章 0 订阅
该博客主要讨论LOJ10051问题,它是一个加强版的LOJ10050。博主指出,由于异或操作的性质,可以构造前缀异或。问题转化为寻找每个位置i的最大异或子段和,这与最大连续子段和问题相似。博主提出使用两个数组L和R,分别从左右两侧更新最优解,实现O(N*30)的时间复杂度解决方案。
摘要由CSDN通过智能技术生成

LOJ10051

这题实际上就是加强版的LOJ10050
由于异或一个数偶数次等于啥也没干,所以异或是可以构造“前缀异或”的
那么固定一个终点 i i ,则我们就是类似“最大连续子段和”一样要找一个max(Si^ Sj) S j )
——这不就是LOJ10050吗!!!

开两个数组L(从左往右),R(从右往左)记录最优解,传递,更新答案即可
O(N30) O ( N ∗ 30 )

#include<bits/stdc++.h>
#define gt() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++)
#define __R register
using namespace std;
static char buf[1000000],*p1=buf,*p2=buf;
const int maxn=(4e5)+5,L=30;
int n,Ans,a[maxn],Pow[maxn],S,fL[maxn],fR[maxn];
struct Trie{
    int tot,s[maxn*L][3];bool p[L+5];
    void insert(int& A,int x){
        __R int rot=0,rot1=0,rot2=0,now=0;
        for(__R int i=L-1;i>=0;i--) rot=s[rot][p[i]=(x>>i)&1]=s[rot][p[i]]?s[rot][p[i]]:++tot;
        for(__R int i=L-1;i>=0;i--){
            rot1=s[rot1][p[i]];
            if(s[rot2][!p[i]]) now|=Pow[i],rot2=s[rot2][!p[i]];else rot2=s[rot2][p[i]];
            if(now+Pow[i]-1<=A) return;
        }
        A=now;
    }
}T1,T2;
int read(){
    int ret=0;char ch=gt();
    while(ch<'0'||ch>'9') ch=gt();
    while(ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=gt();
    return ret;
}
int main(){
    n=read(),Pow[0]=1;
    for(__R int i=1;i<L;i++) Pow[i]=Pow[i-1]<<1;
    T1.insert(fL[0],S=0);for(__R int i=1;i<=n;i++) fL[i]=fL[i-1],T1.insert(fL[i],S^=(a[i]=read()));
    T2.insert(fR[n+1],S=0);for(__R int i=n;i;i--){fR[i]=fR[i+1],T2.insert(fR[i],S^=a[i]);if(i>1&&fL[i-1]+fR[i]>Ans) Ans=fL[i-1]+fR[i];}
    printf("%d\n",Ans);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值