您的位置:首页 > 其它

51Nod 1295 (XOR key)

2016-06-30 16:22 267 查看

题目大意

给出一个长度为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进行异或运算,所能得到的最大值。

分析

这类求xor最大的题,一般考虑从高位开始贪心,尽量找该位不同的数,然后一位位往下做。

题目只有区间查询,于是可以先建一个可持久化Trie。然后?对于每个询问,就这样从高位开始在Trie上往下走,求出一个最大答案。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn=50005,maxm=1550005,Log=30;

int tot,n,q,son[maxm][2],sum[maxm],root[maxn];

bool bz[Log+5];

char c;

int read()
{
int x=0;
for (c=getchar();c<'0' || c>'9';c=getchar());
for (;c>='0' && c<='9';c=getchar()) x=x*10+c-48;
return x;
}

void insert(int v,int &x,int y)
{
x=++tot;
memcpy(son[x],son[y],8);
sum[x]=sum[y]+1;
if (!v) return;
insert(v-1,son[x][bz[v-1]],son[y][bz[v-1]]);
}

int find(int v,int x,int y)
{
if (!v) return 0;
if (sum[son[x][bz[v-1]]]>sum[son[y][bz[v-1]]]) return find(v-1,son[x][bz[v-1]],son[y][bz[v-1]])+(1<<(v-1));
return find(v-1,son[x][1-bz[v-1]],son[y][1-bz[v-1]]);
}

int main()
{
n=read(); q=read();
for (int i=1;i<=n;i++)
{
int x=read();
for (int j=0;j<Log;x/=2) bz[j++]=x % 2;
insert(Log,root[i],root[i-1]);
}
while (q--)
{
int x=read(),l=read(),r=read();
for (int j=0;j<Log;x/=2) bz[j++]=1-(x % 2);
printf("%d\n",find(Log,root[r+1],root[l]));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: