• bzoj 3261最大异或和


    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行,每行一个整数表示询问的答案。

     

     

    题意:应该很清楚了;

    题解:

    ①原题中的式子比较假: 化成max( (a[n] xor x)xor a[p-1] ) p∈[l,r];

    ②前面的now = (a[n] xor x)是一个定值,建立一颗字典树,从高位到低位考虑,一定是尽量选和now的那一位相反的数,对前缀建树,如果类似于普通01字典树,只是把一个数字插入经过的所有节点++,这个可持久的结构维护sum[r]-sum[l-1]第i位的节点值位0或1的个数;

    ③查询时,从高到低枚举位数j,如果和now的j位相反的数个数在sum[r]-sum[l-1]内存在,则进入这个节点,否则进入另一个节点执行同样操作,每次更新选择的数的j位

        

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 using namespace std;
     5 const int N=600010,S = 30;
     6 int n,m,a[N],b[N],x,rt[N],sz,ch[N*S][2],sum[N*S];
     7 char gc(){
     8     static char *p1,*p2,s[1000000];
     9     if(p1==p2) p2=(p1=s)+fread(s,1,1000000,stdin);
    10     return(p1==p2)?EOF:*p1++;
    11 }
    12 int rd(){
    13     int x = 0; char c = gc();
    14     while(c<'0'||c>'9') c = gc();
    15     while(c>='0'&&c<='9') x = x * 10 + c - '0',c = gc();
    16     return x;
    17 }
    18 bool opt(){
    19     char c = gc();
    20     while(c!='A'&&c!='Q') c = gc();
    21     return c=='A';
    22 }
    23 int ins(int last,int val){ 
    24     int k,ret; k = ret = ++sz; 
    25     for(int i = 23;i >= 0;i--){
    26         sum[k] = sum[last] + 1; ch[k][0] = ch[last][0]; ch[k][1] = ch[last][1];
    27         int d = (val>>i)&1;
    28         k = ch[k][d] = ++sz; last = ch[last][d];
    29     }
    30     sum[k] = sum[last] + 1;
    31     return ret;
    32 }
    33 int query(int k1,int k2,int val){
    34     int ret = 0;
    35     for(int i = 23;i >= 0;i--){
    36         int d = (val>>i)&1;
    37         if(sum[ch[k2][d^1]]-sum[ch[k1][d^1]]>0) 
    38         ret|=(1<<i),k1=ch[k1][d^1],k2=ch[k2][d^1];
    39         else k1=ch[k1][d],k2=ch[k2][d];
    40     }
    41     return ret;
    42 }
    43 int main()
    44 {    freopen("bzoj3261.in","r",stdin);
    45     freopen("bzoj3261.out","w",stdout);
    46     n = rd()+1; m = rd();
    47     rt[1]=ins(rt[0],b[1]);
    48     for(int i = 2;i <= n;i++) b[i] = b[i-1]^rd(),rt[i]=ins(rt[i-1],b[i]); 
    49     char s[10];
    50     for(int i = 1;i <= m;i++){
    51         if(opt()){
    52             n++; b[n]=b[n-1]^rd();
    53             rt[n]=ins(rt[n-1],b[n]); 
    54         }
    55         else {
    56             int l = rd(),r = rd(),x = rd();
    57             int tmp = query(rt[l-1],rt[r],b[n]^x);
    58             printf("%d
    ",tmp);
    59         }
    60     }
    61     return 0;
    62 }//by tkys_Austin;
  • 相关阅读:
    多校赛3- Painter 分类: 比赛 2015-07-29 19:58 3人阅读 评论(0) 收藏
    K
    Drainage Ditches 分类: POJ 图论 2015-07-29 15:01 7人阅读 评论(0) 收藏
    Power Network 分类: POJ 2015-07-29 13:55 3人阅读 评论(0) 收藏
    Labeling Balls 分类: POJ 2015-07-28 19:47 10人阅读 评论(0) 收藏
    Network 分类: POJ 图论 2015-07-27 17:18 17人阅读 评论(0) 收藏
    Borg Maze 分类: POJ 2015-07-27 15:28 5人阅读 评论(0) 收藏
    Case of the Zeros and Ones 分类: CF 2015-07-24 11:05 15人阅读 评论(0) 收藏
    滑雪 分类: POJ 2015-07-23 19:48 9人阅读 评论(0) 收藏
    Wormholes 分类: POJ 2015-07-14 20:21 21人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/8645650.html
Copyright © 2020-2023  润新知