您的位置:首页 > 其它

51Nod——1295 XOR key(贪心+可持久化字典树)

2016-08-24 21:53 369 查看
题目来源: HackerRank

基准时间限制:1.5 秒 空间限制:262144 KB

给出一个长度为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

考虑查询的数,我们可以从高位到低位进行贪心。由于只有查询,我们可以建立一个可持久化字典树。然后进行区间的从高位到地位进行贪心

#include <bits/stdc++.h>
#define rr(x) freopen(x,"r",stdin)
#define ww(x) freopen(x,"w",stdout)
using namespace std;
const int Max = 55000;
const int Maxn = 1555000;
const int Log = 30;
int tr[Maxn][2],num[Maxn],root[Max];
bool bt[Log];
int n,m,top,da;
void Insert(int v,int &x,int y) {
x = ++top;
for(int i = 0;i<2;i++) tr[x][i] = tr[y][i];
num[x] = num[y]+1;
if(!v) return ;
Insert(v-1,tr[x][bt[v-1]],tr[y][bt[v-1]]);
}
int qu(int v,int x,int y) {
if(!v) return 0;
if(num[tr[x][bt[v-1]]] > num[tr[y][bt[v-1]]]) return qu(v-1,tr[x][bt[v-1]],tr[y][bt[v-1]])+(1<<(v-1));
else return  qu(v-1,tr[x][1-bt[v-1]],tr[y][1-bt[v-1]]);
return 0;
}
int main() {
top = 0;
scanf("%d %d",&n,&m);
for(int i = 1;i<=n;i++) {
scanf("%d",&da);
for(int j = 0;j<Log;j++,da/=2) bt[j] = da % 2;
Insert(Log,root[i],root[i-1]);
}
int l,r;
for(int i = 1;i<=m;i++) {
scanf("%d %d %d",&da,&l,&r);
for(int j = 0;j<Log;j++,da/=2) bt[j] = (1-(da % 2));
printf("%d\n",qu(Log,root[r+1],root[l]));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: