BZOJ 4260 Codechef REBXOR 可持久化Trie树

题目大意:给定一个长度为 n 的序列,求 1l1r1<l2r2n 使得 (r1i=l1ai)+(r2i=l2ai) 最大,输出这个最大值

傻逼题……
求前缀和,问题转化成了求 0l1<r1l2<r2n 使得 (al1ar1)+(al2ar2) 最大
从大到小枚举 r1 ,边枚举边记录最大的 al2ar2 ,然后求出最大的 al1ar1
用可持久化Trie树即可完成上述操作
时间复杂度 O(nlogn)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 400400
using namespace std;
int n,ans,_max;
int a[M];
struct Trie{
    Trie* son[2];
    int size;
    #define ls son[0]
    #define rs son[1]
    void* operator new (size_t,Trie *_,Trie *__,int ___)
    {
        static Trie mempool[M*32],*C=mempool;
        C->ls=_;
        C->rs=__;
        C->size=___;
        return C++;
    }
    friend Trie* Insert(Trie *p,int x,int digit)
    {
        if(!digit)
            return new (p->ls,p->rs,p->size+1)Trie;
        if(x&digit)
            return new (p->ls,Insert(p->rs,x,digit>>1),p->size+1)Trie;
        else
            return new (Insert(p->ls,x,digit>>1),p->rs,p->size+1)Trie;
    }
    friend int Query(Trie *p1,Trie *p2,int x,int digit)
    {
        if(!digit)
            return 0;
        if(p1->son[bool(~x&digit)]->size - p2->son[bool(~x&digit)]->size)
            return digit | Query(p1->son[bool(~x&digit)],p2->son[bool(~x&digit)],x,digit>>1);
        else
            return Query(p1->son[bool(x&digit)],p2->son[bool(x&digit)],x,digit>>1);
    }
}*mem[M],**tree=mem+1;
int main()
{
    int i;
    cin>>n;
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        a[i]^=a[i-1];
    }
    tree[-1]=new (0x0,0x0,0)Trie;
    tree[-1]->ls=tree[-1]->rs=tree[-1];
    for(i=0;i<=n;i++)
        tree[i]=Insert(tree[i-1],a[i],1<<29);
    for(i=n-1;i;i--)
    {
        _max=max(_max,Query(tree[n],tree[i],a[i],1<<29));
        ans=max(ans,_max+Query(tree[i],tree[-1],a[i],1<<29));
    }
    cout<<ans<<endl;
    return 0;
}
    原文作者:Trie树
    原文地址: https://blog.csdn.net/PoPoQQQ/article/details/48656499
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注