• BZOJ 3261 最大异或和(可持久化Trie)


    Description

    给定一个非负整数序列{a},初始长度为N。
    有M个操作,有以下两种操作类型:
    1、Ax:添加操作,表示在序列末尾添加一个数x,序列的长度N+1。
    2、Qlrx:询问操作,你需要找到一个位置p,满足l<=p<=r,使得:
    a[p] xor a[p+1] xor ... xor a[N] xor x 最大,输出最大是多少。

    Input

    第一行包含两个整数 N  ,M,含义如问题描述所示。   
    第二行包含 N个非负整数,表示初始的序列 A 。 
    接下来 M行,每行描述一个操作,格式如题面所述。   

    Output

    假设询问操作有 T个,则输出应该有 T行,每行一个整数表示询问的答案。

    Sample Input

    5 5
    2 6 4 3 6
    A 1
    Q 3 5 4
    A 4
    Q 5 7 0
    Q 3 6 6
    对于测试点 1-2,N,M<=5 。
    对于测试点 3-7,N,M<=80000 。
    对于测试点 8-10,N,M<=300000 。
    其中测试点 1, 3, 5, 7, 9保证没有修改操作。
    0<=a[i]<=10^7。

    Sample Output

    4
    5
    6
     
    解题思路:
      假如说就问你一个数在一群数中的最大异或,你就想到了01字典树 (详见HDU4825)
    那要是这道题不就是把一个序列的后缀异或和做为一个数,问你区间最大异或
    最大异或好办,就是在字典树上贪心查找,而区间异或,就是在一个只存了l~r这个区间的字典树上贪心
    这就是可持久化字典树了(不要问我这是什么,详解网上遍地都是)
    每个节点建一个新版本,询问r和l-1版本的差集贪心即可。
    当然插入数的时候要以前缀的形式插入,询问时利用两次异或值为0的性质即可。
    可持久化数据结构耗费很大空间
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 struct pnt{
     6     int child[2];
     7     int num;
     8 };
     9 struct KCJTrie{
    10     pnt tr[17000000];
    11     int siz;
    12     void insert(int &spc,int rt,int x)
    13     {
    14         spc=++siz;
    15         int root=spc;
    16         for(int i=30;~i;i--)
    17         {
    18             int tmp=((x&(1<<i))!=0);
    19             tr[root]=tr[rt];
    20             tr[root].num++;
    21             rt=tr[rt].child[tmp];
    22             tr[root].child[tmp]=++siz;
    23             root=tr[root].child[tmp];
    24         }
    25         tr[root].num=tr[rt].num+1;
    26         return ;
    27     }
    28     int query(int spc1,int spc2,int v)
    29     {
    30         int ans=0;
    31         int rt1=spc1,rt2=spc2;
    32         for(int i=30;~i;i--)
    33         {
    34             int tmp=((v&(1<<i))!=0);
    35             if(tr[tr[rt1].child[tmp^1]].num-tr[tr[rt2].child[tmp^1]].num)
    36             {
    37                 ans|=(1<<i);
    38                 rt1=tr[rt1].child[tmp^1];
    39                 rt2=tr[rt2].child[tmp^1];
    40             }else{
    41                 rt1=tr[rt1].child[tmp];
    42                 rt2=tr[rt2].child[tmp];
    43             }
    44         }
    45         return ans;
    46     }
    47 }T;
    48 int a[1000000];
    49 int b[1000000];
    50 int s[1000000];
    51 int n,m;
    52 char cmd[5];
    53 int main()
    54 {
    55     scanf("%d%d",&n,&m);
    56     n++;//看hzwer学长的博客,的确在第一位放0比较好处理,就不用特判l==1的情况了
    57     for(int i=2;i<=n;i++)
    58         scanf("%d",&a[i]);
    59     for(int i=1;i<=n;i++)
    60     {
    61         b[i]=b[i-1]^a[i];
    62         T.insert(s[i],s[i-1],b[i]);
    63     }
    64     for(int i=1;i<=m;i++)
    65     {
    66         scanf("%s",cmd);
    67         if(cmd[0]=='A')
    68         {
    69             n++;
    70             scanf("%d",&a[n]);
    71             b[n]=b[n-1]^a[n];
    72             T.insert(s[n],s[n-1],b[n]);
    73         }else{
    74             int l,r,x;
    75             scanf("%d%d%d",&l,&r,&x);
    76             printf("%d
    ",T.query(s[r],s[l-1],x^b[n]));
    77         }
    78     }
    79     return 0;
    80 }
  • 相关阅读:
    算法笔记_225:数字密码发生器(Java)
    LVS专题-(1)LVS基本介绍
    Mysql加锁过程详解(7)-初步理解MySQL的gap锁
    java实现二叉树的构建以及3种遍历方法
    java设计模式-菜鸟网络
    数据结构与算法(周鹏-未出版)-第六章 树-习题
    数据结构与算法(周鹏-未出版)-第六章 树-6.5 Huffman 树
    数据结构与算法(周鹏-未出版)-第六章 树-6.4 树、森林
    数据结构与算法(周鹏-未出版)-第六章 树-6.3 二叉树基本操作的实现
    数据结构与算法(周鹏-未出版)-第六章 树-6.2 二叉树
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/9457998.html
Copyright © 2020-2023  润新知