bzoj3261 最大异或和(可持久化Tire树)

题目

传送门
给定一个非负整数序列{a},初始长度为N。有M个操作,有以下两种操作类型:
1、A x:添加操作,表示在序列末尾添加一个数x,序列的长度N+1。
2、Q l r x:询问操作,你需要找到一个位置p,满足l<=p<=r,使得:a[p] xor a[p+1] xor … xor a[N] xor x 最大,输出最大是多少。

题解

考虑前缀和
sum[i]表示1.2….i的前缀的异或和,那么题目让求的就是sum[i]^sum[n]^x,选取一个i求其最大值.
每次就用X^=sum[n],再用这样的X在L到R范围内找一个sum使其异或和最大
这就转化成了在一堆数里面选一个数与指定数异或和最大的经典trie树贪心的问题了

那么我们对于每一个新加的节点,都建立一棵tire树是不可以被接受的,类比上面可持久化线段树,主席树的思想,将sum[i]转化为二进制数,然后建立可持久化trie树,根据(sum[n]^x)在tire树上查找;贪心:尽量使异或和为1,不行的话为0;

对于相邻的两棵树,只有一个数不同而已,一个数在trie上对应的就是一条链,建树时我们沿着这条链走,把这条链构造进新树里,其余结构全部指向旧树
就是说新树只有这一条链的部分是新建的,而其他部分全部与旧树共享,类比主席树

代码

#include
#include
#include
using namespace std;
const int maxn=600005;
const int sz=25;
int ans,num,n,m,x,y,k,cnt,tot,root[maxn],sum[maxn*30],ch[maxn*30][2];//tot异或和 ch[][]左右孩子 

void insert(int &now,int x,int dep)//now根 x当前的异或和,dep深度 
{
    sum[++num]=sum[now]+1;
    ch[num][0]=ch[now][0]; ch[num][1]=ch[now][1];
    now=num;
    if (dep==-1) return;
    int k=(x>>dep)&1;//x的第dep位是否为1;区分左右 
    if (!k) insert(ch[now][0],x,dep-1);
    else insert(ch[now][1],x,dep-1);
}

void ques(int L,int R,int x,int dep)
{
    if (dep==-1) return;
    int k=(x>>dep)&1;
    if (sum[ch[R][k^1]]-sum[ch[L][k^1]]>0)
    {
        ans|=1<//或操作有加的一点意思(自行参悟)
        ques(ch[L][k^1],ch[R][k^1],x,dep-1);
    }
    else ques(ch[L][k],ch[R][k],x,dep-1);
}

int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1; i<=n; i++)
    {
        scanf("%d",&x);
        tot^=x; root[i]=root[i-1];
        insert(root[i],tot,sz-1);
    }
    cnt=n;
    for (int i=1;i<=m;++i)
    {
        char opt=getchar();
        while (opt!='A'&&opt!='Q') opt=getchar();
        if (opt=='A')
        {
            scanf("%d",&x);
            tot^=x; root[++cnt]=root[cnt-1];
            insert(root[cnt],tot,sz-1);
        }
        else
        {
            int l,r;
            scanf("%d%d%d",&l,&r,&x);
            ans=0;
            --l,--r;l=max(l,0);r=max(r,0);
            ques(root[l-1],root[r],tot^x,sz-1);
            if (l==0) ans=max(ans,tot^x);
            printf("%d\n",ans);
        }
    }
    return 0;
}

总结

与异或有关的应该联想到Tire树
可持久化数据结构的应用

你可能感兴趣的:(tire,可持久化)