【可持久化Trie】bzoj 3261 hdu 6191

https://www.cnblogs.com/zcysky/p/6910661.html 江山自有人才出,写的很漂亮,代码一看就懂

bzoj 3261有个坑,就是要把第零个数字也加到trie里,否则可能漏算or算错

bzoj 3261代码 

插入的是前缀和,查询的是x^sum[n],贪心得到结果就相当于 x^sum[n]^sum[p-1]=a[p]^a[p+1]...^a[n]^x

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=600060;
 4 int n,m,a[N],b[N];
 5 int cnt,bin[32],c[N*25][2],sum[N*25],rt[N];
 6 struct Trie
 7 {
 8     int ins(int x,int val)
 9     {
10         int y,tmp;y=tmp=++cnt;
11         for(int i=24;i>=0;i--)
12         {
13             c[y][0]=c[x][0];c[y][1]=c[x][1];
14             sum[y]=sum[x]+1;
15             int t=val&bin[i];t=t>>i;
16             x=c[x][t];c[y][t]=++cnt;y=c[y][t];
17         }
18         sum[y]=sum[x]+1;
19         return tmp;
20     }
21     int query(int l,int r,int val)
22     {
23         int re=0;
24         for(int i=24;i>=0;i--)
25         {
26             int t=val&bin[i];t>>=i;
27             if(sum[c[r][t^1]]-sum[c[l][t^1]])
28             {
29                 re+=bin[i];
30                 r=c[r][t^1];l=c[l][t^1];
31             }
32             else r=c[r][t],l=c[l][t];
33         }
34         return re;
35     }
36 }T;
37 void clr()
38 {
39     cnt=0;
40     bin[0]=1;
41     for(int i=1;i<=30;i++)bin[i]=bin[i-1]<<1;    
42     c[0][0]=c[0][1]=0;
43     rt[0]=sum[0]=b[0]=0;
44 }
45 int main()
46 {
47     while(~scanf("%d%d",&n,&m))
48     {
49         clr();
50         n++;//就是这里 
51         for(int i=1;i<=n;i++)
52         {
53             if(i!=1)
54             scanf("%d",a+i);
55             else a[1]=0;
56             b[i]=b[i-1]^a[i];
57             rt[i]=T.ins(rt[i-1],b[i]);
58         }
59         char s[5];
60         for(int i=1;i<=m;i++)
61         {
62             scanf("%s",s);
63             if(s[0]=='A')
64             {
65                 n++;scanf("%d",a+n);
66                 b[n]=b[n-1]^a[n];
67                 rt[n]=T.ins(rt[n-1],b[n]);
68             }
69             else
70             {
71                 int l,r,x;
72                 scanf("%d%d%d",&l,&r,&x);
73                 printf("%d\n",T.query(rt[l-1],rt[r],x^b[n]));
74             }
75         }
76     }
77       return 0;
78 }

hdu 6191

求区间里a[p]异或x最大

#include<bits/stdc++.h>
using namespace std;
const int N=200020;
int n,m;
int g[N],v[N],L[N],R[N],tot,dfn,a[N];
struct point
{
    int to,next;
}e[500050];
void add(int x,int y)
{
    e[++tot].to=y;
    e[tot].next=g[x];
    g[x]=tot;
}
void dfs(int x)
{
    L[x]=++dfn;
    a[dfn]=v[x];
    for(int tmp=g[x];tmp;tmp=e[tmp].next)
    {
        dfs(e[tmp].to);
    }
    R[x]=dfn;
}
int c[N*31][2],sum[N*31],rt[N],cnt,bin[31];
struct Trie
{
    int ins(int x,int val)
    {
        int tmp,y;tmp=y=++cnt;
        for(int i=30;i>=0;i--)
        {
            c[y][0]=c[x][0];c[y][1]=c[x][1];
            sum[y]=sum[x]+1;
            int t=val&bin[i];t>>=i;
            x=c[x][t];c[y][t]=++cnt;y=c[y][t];
        }
        sum[y]=sum[x]+1;
        return tmp;
    }
    int query(int l,int r,int val)
    {
        int re=0;
        for(int i=30;i>=0;i--)
        {
            int t=val&bin[i];t>>=i;
            if(sum[c[r][t^1]]-sum[c[l][t^1]])
            {
                re+=bin[i];
                r=c[r][t^1];
                l=c[l][t^1];
            }
            else r=c[r][t],l=c[l][t];
        }
        return re;
    }
}T;
void clr()
{
    c[0][0]=c[0][1]=0;
    for(int i=0;i<=n;i++)
    rt[i]=g[i]=0;
    cnt=dfn=tot=0;
    bin[0]=1;
    for(int i=1;i<31;i++)bin[i]=bin[i-1]<<1;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        clr();
        for(int i=1;i<=n;i++)
        scanf("%d",&v[i]);
        for(int i=1;i<n;i++)
        {
            int x;
            scanf("%d",&x);
            add(x,i+1);
        }
        dfs(1);
        for(int i=1;i<=n;i++)
        {
            rt[i]=T.ins(rt[i-1],a[i]);
        }
        for(int i=1;i<=m;i++)
        {
            int u,x;
            scanf("%d%d",&u,&x);
            printf("%d\n",T.query(rt[L[u]-1],rt[R[u]],x));
        }
    }
    return 0;
}

(人菜就得多学习

posted @ 2018-04-02 19:40  岚之川  阅读(130)  评论(0编辑  收藏  举报