• 51Nod XOR key —— 区间最大异或值 可持久化字典树


    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1295

    题目来源: HackerRank
    基准时间限制:1.5 秒 空间限制:262144 KB 分值: 160 难度:6级算法题
     收藏
     关注
    给出一个长度为N的正整数数组A,再给出Q个查询,每个查询包括3个数,L, R, X (L <= R)。求A[L] 至 A[R] 这R - L + 1个数中,与X 进行异或运算(Xor),得到的最大值是多少?
    Input
    第1行:2个数N, Q中间用空格分隔,分别表示数组的长度及查询的数量(1 <= N <= 50000, 1 <= Q <= 50000)。
    第2 - N+1行:每行1个数,对应数组A的元素(0 <= A[i] <= 10^9)。
    第N+2 - N+Q+1行:每行3个数X, L, R,中间用空格分隔。(0 <= X <= 10^9,0 <= L <= R < N)
    Output
    输出共Q行,对应数组A的区间[L,R]中的数与X进行异或运算,所能得到的最大值。
    Input示例
    15 8  
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    10 5 9
    1023 6 6
    33 4 7
    182 4 9
    181 0 12
    5 9 14
    99 7 8
    33 9 13
    Output示例
    13  
    1016  
    41  
    191  
    191  
    15  
    107  
    47

    题解:

    1.此题(HDU4825 Xor Sum)的加强版

    2.由于要求的是x与区间[l,r]的某个数异或值最大,所以在Trie树的基础上,可以模仿可持久化线段树,建立一棵可持久化Trie树。这样就可以得到每插入一个数时的历史版本的Trie树。

    代码如下

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <vector>
      6 #include <cmath>
      7 #include <queue>
      8 #include <stack>
      9 #include <map>
     10 #include <string>
     11 #include <set>
     12 using namespace std;
     13 typedef long long LL;
     14 const int INF = 2e9;
     15 const LL LNF = 9e18;
     16 const int MOD = 1e9+7;
     17 const int MAXN = 1e5+10;
     18 
     19 struct Trie
     20 {
     21     int end[303*MAXN], next[33*MAXN][2];
     22     int root[MAXN], L = 0;
     23     int newnode()
     24     {
     25         next[L][0] = next[L][1] = -1;
     26         end[L++] = 0;
     27         return L-1;
     28     }
     29     void init()
     30     {
     31         L = 0;
     32     }
     33     void build(LL val)  //初始化版本
     34     {
     35         int tmp = root[0];
     36         for(int i = 32; i>=0; i--)
     37         {
     38             int way = (val>>i)&1;
     39             if(next[tmp][way]==-1) next[tmp][way] = newnode();
     40             tmp = next[tmp][way];
     41         }
     42     }
     43     int insert(int preroot, LL val)
     44     {
     45         int newroot = newnode(), rootbuf = newroot;
     46         for(int i = 32; i>=0; i--)
     47         {
     48             int way = (val>>i)&1;
     49             next[newroot][way] = newnode(); //要走的路,新开出来
     50             next[newroot][!way] = next[preroot][!way];  //另一条路,指向上一个历史版本的
     51 
     52             newroot = next[newroot][way];
     53             preroot = next[preroot][way];
     54             end[newroot] = end[preroot]+1;  //叠加
     55         }
     56         return rootbuf;
     57     }
     58     LL query(int Lroot, int Rroot, LL val)
     59     {
     60         LL ret = 0;
     61         for(int i = 32; i>=0; i--)
     62         {
     63             ret <<= 1;
     64             int way = (val>>i)&1;
     65             if(next[Lroot][!way]!=-1 && (end[next[Rroot][!way]]-end[next[Lroot][!way]]>0))
     66             {
     67                 ret ^= 1;
     68                 Lroot = next[Lroot][!way];
     69                 Rroot = next[Rroot][!way];
     70             }
     71             else
     72             {
     73                 Lroot = next[Lroot][way];
     74                 Rroot = next[Rroot][way];
     75             }
     76         }
     77         return ret;
     78     }
     79 };
     80 Trie T;
     81 
     82 LL a[MAXN];
     83 int main()
     84 {
     85     int n, q;
     86     while(scanf("%d%d",&n,&q)!=EOF)
     87     {
     88         T.init();
     89         T.root[0] = T.newnode();
     90         for(int i = 1; i<=n; i++)   //建立初始化版本
     91         {
     92             scanf("%lld",&a[i]);
     93             T.build(a[i]);
     94         }
     95         for(int i = 1; i<=n; i++)   //每插入一个数,就生成一个历史版本的Trie树
     96             T.root[i] = T.insert(T.root[i-1],a[i]);
     97 
     98         while(q--)
     99         {
    100             int x, l, r;
    101             scanf("%d%d%d",&x,&l,&r);
    102             l++; r++;
    103             printf("%lld
    ", T.query(T.root[l-1],T.root[r],1LL*x));
    104         }
    105     }
    106 }
    View Code
  • 相关阅读:
    以前给工大软件学院作得首页
    rinruby
    螃蟹为什么煮熟后会变红?
    关于R中利用apply、tapply、lapply、sapply、mapply、table
    hp laserjet 1020驱动 for windows
    关于睡觉巻起来姿势
    王强英語
    进程的前后台切换
    研究生=烟酒生
    计算矩阵乘法的网页工具
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/8728061.html
Copyright © 2020-2023  润新知