BZOJ3261:最大异或和(可持久化trie)

题面

刚学

trie的可持久化可以快速建一棵和已知trie相似的trie
从而做到保存历史版本,在线构造两棵trie的差并查询

运用位运算与trie的联系就可以搞完这题了

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
#define mmst(a, b) memset(a, b, sizeof(a))
#define mmcp(a, b) memcpy(a, b, sizeof(b))

typedef long long LL;

const int N=600600;

int n,m;
int a[N];
int er[50];
int ro[N],son[N*24][2],sum[N*24],cnt;
char cc[5];

int Insert(int x,int val)
{
    int res,y;
    res=y=++cnt;

    for(int i=23;i>=0;i--)
    {
        son[y][0]=son[x][0];
        son[y][1]=son[x][1];
        sum[y]=sum[x]+1;

        int t=(val&er[i])>>i;

        x=son[x][t];
        son[y][t]=++cnt;
        y=son[y][t];
    }
    sum[y]=sum[x]+1;
    return res;
}

int query(int l,int r,int val)
{
    int res=0;
    for(int i=23;i>=0;i--)
    {
        int t=(val&er[i])>>i;
        if(sum[son[r][t^1]]-sum[son[l][t^1]])
        {
            res+=er[i];
            r=son[r][t^1];
            l=son[l][t^1];
        }
        else
        {
            r=son[r][t];
            l=son[l][t];
        }
    }
    return res;
}

int main()
{
    er[0]=1;
    for(int i=1;i<=30;i++)
    er[i]=er[i-1]*2;

    cin>>n>>m;
    n++;
    ro[1]=Insert(0,0);
    for(int i=2;i<=n;i++)
    {
        scanf("%d",&a[i]);
        a[i]^=a[i-1];
        ro[i]=Insert(ro[i-1],a[i]);
    }

    while(m--)
    {
        int l,r,x;
        scanf("%s",cc);

        if(cc[0]=='A')
        {
            n++;
            scanf("%d",&a[n]);
            a[n]^=a[n-1];
            ro[n]=Insert(ro[n-1],a[n]);
        }
        else
        {
            scanf("%d%d%d",&l,&r,&x);
            printf("%d\n",query(ro[l-1],ro[r],a[n]^x));
        }
    }

    return 0;
}

你可能感兴趣的:(trie)