bzoj 3261: 最大异或和

表示bzoj把本校大佬Cherish_OI当成僵尸用户(ORZ

现在都还在封我们学校IP(管理员怕是看不到我的blog。。。

OK那么这题又get一个新姿势,可持久化字典树。听说这东西解决异或和是常规操作?

这个东西呢,我第一感觉就是跟主席树很像,然后吐槽一波空间消耗极大

对于每个前缀异或和建树,然后前缀和,这里的前缀和是每个位0,1的数量(就是主席树嘛)

然后query的时候,因为答案是sum[p-1]^sum[n]^x,而sum[n]^x已知,那么就去字典树里l-1~r的区间由大到小去找和sum[n]^x的当前二进制位不同数是否存在,也就是if(当前区间c>0),就是记录答案。

细节:一开始要插一个0的数,因为当p取1,也就是如果我们把全部的数异或起来是最大的,那答案就是sum[n]^x,在前面多增加一位方便。并且如果不这么做,找的时候就要从l-2~r-1里面找,因为前缀和的缘故sum的总数是要比值的数量少1的。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

int Bin[30];
struct Trie
{
    int w[2],sum;
}tr[21000000];int trlen,rt[610000];
int maketree(int x,int d)
{
    int y=++trlen;int ret=y;
    for(int i=23;i>=0;i--)
    {
        tr[y].w[0]=tr[x].w[0];
        tr[y].w[1]=tr[x].w[1];
        tr[y].sum=tr[x].sum+1;
        
        int t;
        if((d&Bin[i])==0)t=0;
        else t=1;
        
        x=tr[x].w[t];
        tr[y].w[t]=++trlen;
        y=tr[y].w[t];
    }
    tr[y].sum=tr[x].sum+1;
    return ret;
}
int query(int x,int y,int d)
{
    int ans=0;
    for(int i=23;i>=0;i--)
    {
        int t;
        if((d&Bin[i])==0)t=0;
        else t=1;
        
        if(tr[tr[y].w[t^1]].sum-tr[tr[x].w[t^1]].sum>0)
        {
            ans+=Bin[i];
            x=tr[x].w[t^1], y=tr[y].w[t^1];
        }
        else
            x=tr[x].w[t], y=tr[y].w[t];
    }
    return ans;
}

int a[610000],s[610000];
char ss[10];
int main()
{
    Bin[0]=1;for(int i=1;i<=30;i++)Bin[i]=Bin[i-1]*2;
    int n,m;
    scanf("%d%d",&n,&m);n++;
    s[1]=0;
    for(int i=2;i<=n;i++)
        scanf("%d",&a[i]), s[i]=s[i-1]^a[i];
    trlen=0;
    for(int i=1;i<=n;i++)
        rt[i]=maketree(rt[i-1],s[i]);
    
    int l,r,p;
    while(m--)
    {
        scanf("%s",ss+1);
        if(ss[1]=='A')
        {
            n++;
            scanf("%d",&a[n]), s[n]=s[n-1]^a[n];
            rt[n]=maketree(rt[n-1],s[n]);
        }
        else
        {
            scanf("%d%d%d",&l,&r,&p);
            printf("%d\n",query(rt[l-1],rt[r],s[n]^p));
        }
    }
    return 0;
}

 

posted @ 2018-03-26 08:57  AKCqhzdy  阅读(231)  评论(0编辑  收藏  举报