51Nod - 1295:XOR key (可持久化Trie求区间最大异或)

给出一个长度为N的正整数数组A,再给出Q个查询,每个查询包括3个数,L, R, X (L <= R)。求ALL 至 ARR 这R - L + 1个数中,与X 进行异或运算(Xor),得到的最大值是多少?Input第1行:2个数N, Q中间用空格分隔,分别表示数组的长度及查询的数量(1 <= N <= 50000, 1 <= Q <= 50000)。 
第2 - N+1行:每行1个数,对应数组A的元素(0 <= Aii <= 10^9)。 
第N+2 - N+Q+1行:每行3个数X, L, R,中间用空格分隔。(0 <= X <= 10^9,0 <= L <= R < N)Output输出共Q行,对应数组A的区间L,RL,R中的数与X进行异或运算,所能得到的最大值。Sample 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

Sample Output

13
1016
41
191
191
15
107
47

懒得说了。反正主席树写习惯了,持久化Trie也就直接写了。

#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
int a[maxn],rt[maxn],cnt;
struct node{
    int l,r,val;
    node(){ l=r=val=0; }
    node(int L,int R,int V):l(L),r(R),val(V){}
}s[maxn*20];
void add(int &now,int pre,int x,int pos)
{
    now=++cnt;
    s[now]=node(s[pre].l,s[pre].r,s[pre].val+1);
    if(pos==-1) return ;
    if(((x>>pos)%2)==0) add(s[now].l,s[pre].l,x,pos-1);
    else add(s[now].r,s[pre].r,x,pos-1);
}
int query(int now,int pre,int x)
{
    int res=0;
    for(int i=30;i>=0;i--){
        int t=(x>>i)%2;
        if(t==0){
            if(s[now].r&&s[s[now].r].val-s[s[pre].r].val>0) now=s[now].r, pre=s[pre].r, res+=(1<<i);
            else now=s[now].l, pre=s[pre].l;
        }
        if(t==1){
            if(s[now].l&&s[s[now].l].val-s[s[pre].l].val>0) now=s[now].l, pre=s[pre].l, res+=(1<<i);
            else now=s[now].r, pre=s[pre].r;
        }
    }
    return res;
}
int main()
{
    int N,Q,L,R,x,i;
    scanf("%d%d",&N,&Q);
    for(i=1;i<=N;i++){
        scanf("%d",&a[i]);
        add(rt[i],rt[i-1],a[i],30);
    }
    for(i=1;i<=Q;i++){
        scanf("%d%d%d",&x,&L,&R);
        int ans=query(rt[R+1],rt[L],x);
        printf("%d\n",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/hua-dong/p/9126937.html

时间: 2024-10-10 04:16:28

51Nod - 1295:XOR key (可持久化Trie求区间最大异或)的相关文章

[51nod 1295]Xor key(可持久化trie)

[51nod 1295]Xor key(可持久化trie) 题面 给出一个长度为n的正整数数组A,再给出Q个查询,每个查询包括3个数,L, R, X (L <= R).求A[L] 至 A[R] 这R - L + 1个数中,与X 进行异或运算(Xor),得到的最大值是多少? 分析 可持久化trie裸题 代码 #include<iostream> #include<cstdio> #define maxb 31 #define maxn 200000 #define maxs 6

51nod 1295 XOR key (可持久化Trie树)

1295 XOR key  题目来源: 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 <= 

【函数式Trie】51NOD 1295 XOR key

通道 思路:每个数建个31位的树,处理好关系即可 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 60007; const int BIT = 32; int n, m; int tot, s[N * BIT], a[N * BIT][2], root[N]; void Insert(int x, int &y, in

BZOJ5338 [TJOI2018] Xor 【可持久化Trie树】【dfs序】

题目分析: 很无聊的一道题目.首先区间内单点对应异或值的询问容易想到trie树.由于题目在树上进行,case1将路径分成两段,然后dfs的时候顺便可持久化trie树做询问.case2维护dfs序,对dfs序建可持久化的trie树.这样做的空间复杂度是O(nw),时间复杂度是O(nw). 代码: 1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=102000; 5 6 int n,q; 7 int v[maxn

【可持久化Trie】bzoj3261 最大异或和

对原序列取前缀异或值,变成pre[1...N],然后询问等价于求max{a[N]^x^pre[i]}(l-1<=i<=r-1). #include<cstdio> #define INF 2147483647 #define N 300001 #define MAXBIT 25 int root[N<<1],ch[(N<<1)*(MAXBIT+1)][2],sz[(N<<1)*(MAXBIT+1)],tot; int query(int L,in

[01字典树]求序列完美度(求区间最大异或值)

https://nanti.jisuanke.com/t/15531 解题关键:01字典树模板,用字典树保存每个数的二进制表示,从而动态维护区间上的最大异或值,注意添加和删除都可以用于一个change函数表示. 复杂度:$O(n\log n + {n^2}\log n)$ 1 #include<bits/stdc++.h> 2 #define maxn 1005 3 #define inf 0x3f3f3f3f 4 using namespace std; 5 typedef long lon

[Luogu P4735]最大异或和(可持久化Trie)

[Luogu P4735]最大异或和(可持久化Trie) 题面 给定一个非负整数序列{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 最大,输出最大是多少. 分析 维护\(sum[i]=sum[i-1] \ \text{XOR} \ a[i]\),那么答案就是\(sum[

[bzoj3261]最大异或和[可持久化trie树]

因为要求异或和最大,所以可以考虑从高位开始,向低位枚举尽可能接近~x的值,所以以二进制位为关键字,建立可持久化trie树,根据异或和的性质,XOR_SUM{i,j}=XOR_SUM{1,j} xor XOR_SUM{1,i-1},所以查询问题也可以解决了. 1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <c

【暖*墟】#数据结构# 可持久化Trie 与 XOR问题

0/1 Trie [例题]最长异或路径 给定一棵n个点的带权树,求树中最长的异或路径. Solution 01字典树:用于解决xor问题. 用dis[i]表示‘从i点到根节点的路径异或和’. ---> 那么问题转化为:求两点dis的异或最大值. 一般查询两数的最大异或值时,都是从最高位到最低位,由此建立Trie树. 利用贪心的思想:对 dis[ ] 建一棵trie树,对于每个数,每次选相反的位置. 即:如果x这一位是1,在tire树上往0跑,反之往1跑. #include<iostream&g