bzoj-4260 Codechef REBXOR

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xu0_zy/article/details/83445468

题目链接

题目大意
给出一个序列求MAX{ (a[L1] xor a[L1+1] xor … xor a[R1])+(a[L2] xor a[L2+1] xor…xor a[R2]) }

其中,1≤L1≤R1 < L2≤R2≤N 。

数据范围:2≤N≤4*10^ 5,0≤a[i]≤10^9 。

题解
这题比较裸吧。(本文所有前缀和默认理解为异或缀和)。

异或是可以利用前缀和来弄的,那么我们肯定毫不犹豫地做一趟前缀和。

两个区间是相似的,如果我们能求出一个区间,那么另一个区间是同理的,只需规定一下范围就好了。

接着思考如何求一个区间,即对于 s[i] ^ s[j],s[j] 取谁的时候最优?

显然,从高位开始,尽可能和 s[i] 错开。例如
(二进制下)
s[i]=11001 那么 s[j]=01001 时显然比 s[j]=10110 时好。
如果能找到一个 s[j] 让高位同 s[i] 错开,那么即使后面全部对上,也比高位对上的来的优秀。

怀着这样的想法,我们就需要这么一个能够按位查询是否存在这样一个元素的数据结构,显然 Trie 树可以胜任。

由此我们可以构造出一个数组 L[i] 表示 L1 位置不知道,R1 位置为 i 的最大区间异或和。
经过修正可以用来表示 L1 位置不知道,R1 的位置不大于 i 的最大区间异或和。
同理可以求出一个类似的 R[i],那么 ans=MAX{ L[i]+R[i+1] }

代码
这题写到我抓狂,为什么指针那么慢?
原版跑 9 s 多,拼死优到 6.8s 再优不了了。

指针版:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=4e5+5,maxp=15000000;
int n,a[maxn],e[35],len=32,T,L[maxn],R[maxn];
#define LL long long
LL ans;
struct js{
    js*son[2];
    js(){son[0]=son[1]=NULL;}
    void cl(){son[0]=son[1]=NULL;}
}*top,ne_[maxp+1];
int rad()
{
    int ret=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
    return ret*f;
}
int nxt(){return(++T)>=maxp?(T=0):T;}
void set_()//Trie树的插入
{
    if (top==NULL) {top=&ne_[nxt()];top->cl();}
    js*x=top;
    for (int i,stp=len;stp;--stp)
    {
        i=e[stp];
        if (x->son[i]==NULL) {x->son[i]=&ne_[nxt()];x->son[i]->cl();}
        x=x->son[i];
    }
}
void get_(int&ans)//求L[i]的第一个定义。
{
	js*x=top;
    for (int i,stp=len;x!=NULL&&stp;--stp)
    {
        i=e[stp];
        if (x->son[i^1]!=NULL)
        {
            ans|=1<<stp-1;
            x=x->son[i^1];
        }else
        {
            if (ans&1<<stp-1) ans^=1<<stp-1;;
            x=x->son[i];
        }
    }
}
void ready(int x)//拆数,拆成“字符串”,用于Trie数
{
    for (int i=1;i<=32;++i) e[i]=x&1,x>>=1;
}
int main()
{
//	freopen("OL.in","r",stdin);freopen("OL.out","w",stdout);
    n=rad();
    top=NULL;
    ready(0);
    set_();
    for (int i=1,XOR=0,sum;i<=n;++i)
    {
        XOR^=a[i]=rad();
        ready(XOR);
        sum=XOR;
        get_(sum);
        L[i]=max(L[i-1],sum);
        set_();
    }
    top=NULL;
    ready(0);
    set_();
    for (int i=n,XOR=0,sum;i>=1;--i)
    {
        XOR^=a[i];
        ready(XOR);
        sum=XOR;
        get_(sum);
        R[i]=max(R[i+1],sum);
        set_();
    }
    ans=0;
    for (int i=1;i<n;++i)
      ans=max(ans,(LL)L[i]+R[i+1]);
    printf("%lld\n",ans);
    return 0;
}

数组版也差不多慢,6.8 左右。
数组版:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=4e5+5,maxp=15000000,len=32;
int n,a[maxn],e[35],T,L[maxn],R[maxn];
#define LL long long
LL ans;
struct js{
    int son[2];
    js(){son[0]=son[1]=0;}
    void cl(){son[0]=son[1]=0;}
}t[maxp+1];
int rad()
{
    int ret=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
    return ret*f;
}
int nxt(){return(++T)>=maxp?(T=0):T;}
void set_()
{
    int x=1;
    for (int i,stp=len;stp;--stp)
    {
        i=e[stp];
        if (t[x].son[i]==0) {t[x].son[i]=nxt();t[t[x].son[i]].cl();}
        x=t[x].son[i];
    }
}
int get_()
{
	int x=1,ret=0;
    for (int i,stp=len;x!=0&&stp;--stp)
    {
        i=e[stp];
        if (t[x].son[i^1]!=0)
        {
            ret|=1<<stp-1;
            x=t[x].son[i^1];
        }else x=t[x].son[i];
    }
    return ret;
}
void ready(int x){for (int i=1;i<=32;++i) e[i]=x&1,x>>=1;}
int main()
{
//	freopen("OL.in","r",stdin);freopen("OL.out","w",stdout);
    t[1].cl();ready(0);set_();n=rad();
    for (int i=1,XOR=0;i<=n;++i)
    {
        ready(XOR^=a[i]=rad());
        L[i]=max(L[i-1],get_());
        set_();
    }
    t[1].cl();ready(0);set_();
    for (int i=n,XOR=0;i>=1;--i)
    {
        ready(XOR^=a[i]);
        R[i]=max(R[i+1],get_());
        ans=max(ans,(LL)L[i]+R[i+1]);
        set_();
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xu0_zy/article/details/83445468