51nod 1295 XOR key (可持久化Trie树)
给出一个长度为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
思路:
可持久化Trie树模板题,不加输入输出是优化也可以过,加了会减很多耗时,之前数组开小了,超时了好几发。
参考博客:
https://www.cnblogs.com/RabbitHu/p/51nod1295.html
实现代码:
#include<bits/stdc++.h> using namespace std; #define ll long long const int M = 1e5+10; int a[M]; int rt[M]={1},siz[M<<5],son[M<<5][2],idx; template <class T> void read(T &x){ char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x){ if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } void Insert(int i,int x){ int now = rt[i] = ++idx; int old = rt[i-1]; for(int i = 31;i >= 0;i --){ siz[now] = siz[old] + 1; if((x >> i)& 1) son[now][0] = son[old][0],son[now][1] = ++idx; else son[now][1] = son[old][1],son[now][0] = ++idx; now = son[now][(x>>i)&1]; old = son[old][(x>>i)&1]; } siz[now] = siz[old] + 1; } int query(int l,int r,int x){ int now = rt[r],old = rt[l],ans = 0; for(int i = 31;i >= 0;i --){ int dir = (x >> i)&1; int delta_siz = siz[son[now][!dir]] - siz[son[old][!dir]]; if(delta_siz) now = son[now][!dir],old = son[old][!dir],ans = ans <<1 |1; else now = son[now][dir],old = son[old][dir],ans = ans << 1; } return ans; } int main(){ int n,q,l,r,x; idx = 1; read(n);read(q); for(int i = 1;i <= n;i ++){ read(a[i]); } for(int i = 1;i <= n;i ++) Insert(i,a[i]); while(q--){ read(x);read(l);read(r); write(query(l,r+1,x)); putchar('\n'); } return 0; }