3261: 最大异或和 可持久化trie

想学习一下可持久化trie..结果发现没什么要学的,和主席树一样啊,把线段树改成字典树就行了。

#include<iostream>
#include<cstdio>
#define N 600005
using namespace std;
int n,m;
int a[N],b[N],root[N];
inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
struct trie
{
    int cnt;
    int tree[N*24][2],sum[N*24];
    inline int insert(int x,int val)
    {
        int tmp,y; tmp=y=++cnt;
        for (int i=23;~i;i--)
        {
            tree[y][0]=tree[x][0]; tree[y][1]=tree[x][1];
            sum[y]=sum[x]+1;
            int t=val&(1<<i);
            t>>=i;
            x=tree[x][t];
            tree[y][t]=++cnt;
            y=tree[y][t];
        }
        sum[y]=sum[x]+1;
        return tmp;
    }
    inline int query(int l,int r,int val)
    {
        int tmp=0;
        for (int i=23;~i;i--)
        {
            int t=val&(1<<i); t>>=i; t^=1;
            if (sum[tree[r][t]]-sum[tree[l][t]])
                tmp|=(1<<i),r=tree[r][t],l=tree[l][t];
            else r=tree[r][t^1],l=tree[l][t^1];
        }
        return tmp;
    }
}trie;
int main()
{
    n=read(); m=read();
    n++;
    for (int i=2;i<=n;i++) a[i]=read();
    for (int i=1;i<=n;i++) b[i]=b[i-1]^a[i];
    for (int i=1;i<=n;i++)
        root[i]=trie.insert(root[i-1],b[i]);
    while (m--)
    {
        char opt[5];
        scanf("%s",opt);
        if (opt[0]=='A')
        {
            n++;
            a[n]=read(); b[n]=b[n-1]^a[n];
            root[n]=trie.insert(root[n-1],b[n]);
        }
        else
        {
            int l=read(),r=read(),x=read();
            printf("%d\n",trie.query(root[l-1],root[r],b[n]^x));
        }
    }
    return 0;
}

你可能感兴趣的:(3261: 最大异或和 可持久化trie)