zoukankan      html  css  js  c++  java
  • 【BZOJ 3261】最大异或和【可持久化字典树】

    题意

      给出一个长度为n的整数序列,给出m个操作。操作有两种。1,Ax表示在序列结尾增加x。2,Qlrx表示找到一个位置p满足 l<=p<=r,使得a[p] xor a[p+1]xor...xor a[n] xor x最大,并输出这个最大值。

    分析

     今天学可持久化字典树的时候的找的一道模板题。对于这个题目其实只要学过主席树应该都能自己写出来(我照着主席树的套路写然后debug一下午然后发现num数组想错了mmp)

       我们定义sum[i]为a[1]xor a[2] xor ...xor a[i]。那么对于每个询问操作Qlrx,我们要找出一个[l,r]内的p使得sum[n]xor sum[p-1] xor x最大.而显然sum[n]xor x是一个常数,所以我们要找到一个p使得sum[p-1]xor某个常数最大。

       字典树的经典用法就是在一堆数字中,查询某个与x异或最大的是哪个数字。但是这个问题中有区间限制,所以我们需要将其可持久化。与线段树一样,我们记录每个历史版本,也就是前i个数字组成的字典树,根为root[i]。建树的思路和主席树几乎是完全一样的。只不过我们为了实现查询,多更新了一个num数组。因为主席树查询时候可以直接相减得到这个区间内各个数的数量,但是字典树不行,所以我们多维护一个num,来确定在[l,r]区间内,这个节点有没有走向0或者1的方法。

      

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <cstring>
     5 
     6 
     7 using namespace std;
     8 const int maxn=600000*24;
     9 int n,m,sz;
    10 int ch[maxn][2],a[maxn],root[maxn],sum[maxn],val[maxn],num[maxn][2];
    11 void update(int x,int y,int aa,int id){
    12     root[x]=++sz;
    13     x=root[x];
    14     for(int i=23;i>=0;i--){
    15         int c=(aa>>i)&1;
    16         num[x][c]+=num[y][c]+1;
    17         num[x][!c]=num[y][!c];
    18         ch[x][!c]=ch[y][!c];
    19         ch[x][c]=++sz;
    20         memset(ch[sz],0,sizeof(ch[sz]));
    21         x=ch[x][c],y=ch[y][c];
    22     }
    23     val[x]=id;
    24 }
    25 
    26 int query(int x,int y,int aa){
    27     for(int i=23;i>=0;i--){
    28         int c=(aa>>i)&1;
    29         if(num[x][!c]-num[y][!c])
    30             x=ch[x][!c],y=ch[y][!c];
    31         else
    32             x=ch[x][c],y=ch[y][c];
    33     }
    34     return val[x];
    35 }
    36 
    37 int main(){
    38     scanf("%d%d",&n,&m);
    39     sz=1;
    40     sum[0]=0;
    41     update(0,0,0,0);
    42     for(int i=1;i<=n;i++){
    43         scanf("%d",&a[i]);
    44         sum[i]=sum[i-1]^a[i];
    45         update(i,root[i-1],sum[i],i);
    46     }
    47     char c;
    48     int l,r,x;
    49     for(int i=1;i<=m;i++){
    50         scanf(" %c",&c);
    51         if(c=='A'){
    52             n++;
    53             scanf("%d",&a[n]);
    54             sum[n]=sum[n-1]^a[n];
    55             update(n,root[n-1],sum[n],n);
    56         }else{
    57             scanf("%d%d%d",&l,&r,&x);
    58             printf("%d
    ",sum[query(root[r-1],root[l-2],x^sum[n])]^sum[n]^x);
    59         }
    60     }
    61 return 0;
    62 }
    63 //LQL
    View Code
  • 相关阅读:
    基于mini2440的boa服务器移植
    主机+虚拟机ubuntu+mini2440开发板互相ping通
    poj3133 插头dp
    2015 北京网络赛 E Border Length hihoCoder 1231 树状数组 (2015-11-05 09:30)
    2015 北京网络赛 C Protecting Homeless Cats hihoCoder 1229 树状数组
    acm 2015北京网络赛 F Couple Trees 主席树+树链剖分
    hdu4777 树状数组
    hdu5517 二维树状数组
    Codeforces Round #327 (Div. 1) D. Top Secret Task
    2014-2015 ACM-ICPC, Asia Xian Regional Contest GThe Problem to Slow Down You
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/9495318.html
Copyright © 2011-2022 走看看