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\n", T.query(T.root[l-1],T.root[r],1LL*x));
104         }
105     }
106 }
View Code

 

转载于:https://www.cnblogs.com/DOLFAMINGO/p/8728061.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值