• 数据结构&字符串:可持久化字典树


    利用可持久化Trie树实现范围内取值异或最大值

    如果标题没有表达清楚意思,可以看这里的题干:

    然后根据异或的性质,异或一个数两次相当于没有异或,那么我们可以维护一个异或前缀和

    有了异或前缀和之后我们就可以通过前缀和的形式O(1)提取出任意的一个异或区间出来

    然后就可以把题目转化成这样的形式

    求max(b[p]^b[n]^x) (l-1<=p<=r-1)

    这里只有b[p]是不知道的,我们提前把序列的异或前缀和预处理出来之后插入到可持久化Tire树里面,又因为b[n]和x是定值,这就又转化成上一篇博文中描述的问题了

    只不过这里插入到Trie树里面的东西不是独立的,而是一个整体,我们要从这个整体异或中提取出关键的那一个结果来,由于我们的p是限定了范围的,那么这就相当于对应了一系列的前缀和

    范围内的每一个结果都是可行的,因此我们凭借着贪心的时候能取最大取最大的思路,如果在当前Trie树里得不到局部最优解,就跳跃到另一颗更优的Trie树上进行就好了

    可持久化的思想就是每一个版本的树的儿子之间乱跳

     1 #include<cstdio>
     2 const int maxn=600005;
     3 inline int read()
     4 {
     5     int x=0,f=1;char ch=getchar();
     6     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     7     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     8     return x*f;
     9 }
    10 int n,m;
    11 int a[maxn],b[maxn],bin[30],root[maxn];
    12 struct Trie
    13 {
    14     int cnt;
    15     int ch[maxn*24][2],sum[maxn*24];
    16     int insert(int x,int val)
    17     {
    18         int tmp,y;
    19         tmp=y=++cnt;
    20         for(int i=23;i>=0;i--)
    21         {
    22             ch[y][0]=ch[x][0];
    23             ch[y][1]=ch[x][1];
    24             sum[y]=sum[x]+1;
    25             int t=val&bin[i];t>>=i;
    26             x=ch[x][t];
    27             ch[y][t]=++cnt;
    28             y=ch[y][t];
    29         }
    30         sum[y]=sum[x]+1;
    31         return tmp;
    32     }
    33     int query(int l,int r,int val)
    34     {
    35         int tmp=0;
    36         for(int i=23;i>=0;i--)
    37         {
    38             int t=val&bin[i];t>>=i;
    39             if(sum[ch[r][t^1]]-sum[ch[l][t^1]])
    40                 tmp+=bin[i],r=ch[r][t^1],l=ch[l][t^1];
    41             else r=ch[r][t],l=ch[l][t];
    42         }
    43         return tmp;
    44     }
    45 }trie;
    46 int main()
    47 {
    48     bin[0]=1;
    49     for(int i=1;i<30;i++) bin[i]=bin[i-1]<<1;
    50     n=read();m=read();
    51     n++;
    52     for(int i=2;i<=n;i++) a[i]=read();
    53     for(int i=1;i<=n;i++) b[i]=b[i-1]^a[i];
    54     for(int i=1;i<=n;i++)
    55         root[i]=trie.insert(root[i-1],b[i]);
    56     char ch[5];
    57     int l,r,x;
    58     while(m--)
    59     {
    60         scanf("%s",ch);
    61         if(ch[0]=='A')
    62         {
    63             n++;
    64             a[n]=read();b[n]=b[n-1]^a[n];
    65             root[n]=trie.insert(root[n-1],b[n]);
    66         }
    67         else
    68         {
    69             l=read();r=read();x=read();
    70             printf("%d
    ",trie.query(root[l-1],root[r],b[n]^x));
    71         }
    72     }
    73     return 0;
    74 }
  • 相关阅读:
    nginx php-fpm 输出php错误日志
    图解phpstorm常用快捷键
    Mysq性能分析 —— Genral log(普通日志)与 Slow log(慢速日式)
    Mac Terminal
    Git安装与配置
    Linux ulimit
    tcpdump
    Linux 基础
    TCP
    HTTP
  • 原文地址:https://www.cnblogs.com/aininot260/p/9520075.html
Copyright © 2020-2023  润新知