BZOJ 3261 最大异或和

Posted on 2016-05-27 19:55  ziliuziliu  阅读(205)  评论(0编辑  收藏  举报

可持久化trie。

一个重要的思想是前缀和。

然后SB错误调了一晚上。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 600500
using namespace std;
int n,m,x,y,z,tot=0,tree[maxn*25][3],sum[maxn*25],root[maxn];
int a[maxn],b[maxn],bin[30];
char type[4];
void gettable()
{
    bin[0]=1;
    for (int i=1;i<=24;i++)
        bin[i]=bin[i-1]<<1;
}
void insert(int bitt,int last,int &now,int x)
{
    now=++tot;
    tree[now][0]=tree[last][0];tree[now][1]=tree[last][1];
    sum[now]=sum[last]+1;
    if (bitt==-1) return;
    int tmp=x&bin[bitt];tmp>>=bitt;
    insert(bitt-1,tree[last][tmp],tree[now][tmp],x);
}
int query(int bitt,int last,int now,int x)
{
    if (bitt==-1) return 0;
    int tmp=x&bin[bitt];tmp>>=bitt;
    if (sum[tree[now][tmp^1]]-sum[tree[last][tmp^1]])
        return query(bitt-1,tree[last][tmp^1],tree[now][tmp^1],x)+bin[bitt];
    else return query(bitt-1,tree[last][tmp],tree[now][tmp],x);
}
void work1()
{
    n++;
    scanf("%d",&x);
    a[n]=x;b[n]=b[n-1]^x;
    insert(23,root[n-1],root[n],b[n]);
}
void work2()
{
    scanf("%d%d%d",&x,&y,&z);
    printf("%d\n",query(23,root[x-1],root[y],b[n]^z));
}
int main()
{
    gettable();
    scanf("%d%d",&n,&m);
    n++;a[1]=0;b[1]=0;
    for (int i=2;i<=n;i++)
    {
        scanf("%d",&a[i]);
        b[i]=b[i-1]^a[i];
    }    
    for (int i=1;i<=n;i++)
        insert(23,root[i-1],root[i],b[i]);
    for (int i=1;i<=m;i++)
    {
        scanf("%s",type);
        if (type[0]=='A') work1();
        else work2();
    }
    return 0;
}