【题解 P8773】 选数异或

[蓝桥杯 2022 省 A] 选数异或

题目描述

给定一个长度为 n 的数列 A1,A2,,An 和一个非负整数 x, 给定 m 次查询, 每次询问能否从某个区间 [l,r] 中选择两个数使得他们的异或等于 x

输入格式

输入的第一行包含三个整数 n,m,x

第二行包含 n 个整数 A1,A2,,An

接下来 m 行,每行包含两个整数 li,ri 表示询问区间 [li,ri]

输出格式

对于每个询问, 如果该区间内存在两个数的异或为 x 则输出 yes, 否则输出 no

样例 #1

样例输入 #1

4 4 1
1 2 3 4
1 4
1 2
2 3
3 3

样例输出 #1

yes
no
yes
no

提示

【样例说明】

显然整个数列中只有 2,3 的异或为 1 。

【评测用例规模与约定】

对于 20% 的评测用例, 1n,m100;

对于 40% 的评测用例, 1n,m1000;

对于所有评测用例, 1n,m105,0x<220,1lirin0Ai<220

蓝桥杯 2022 省赛 A 组 D 题。

解题思路

对于区间内两个数 al,ar ,若他们 alar=x ,则有 arx=al
预处理出每个 ar 前与他距离最近的且满足要求的 al 的下标,设为 prer
那么,若一段区间 [l,r] 内存在两个数异或和为 x ,必存在一个 ar ,其 prerl
那就是求 maxi=lrprei 是否 l 就好了。
可以用线段树或 ST 表,时间复杂度 O(nlogn)

#include<bits/stdc++.h>
using namespace std;
long long n,m,k,a[100005],last[100005],b[1000005],f[100005][21],p[21],l[100005];
long long dijah(long long x,long long y)
{
	long long z=l[y-x+1];
	return max(f[x][z],f[y-p[z]+1][z]);
}
int main()
{
	long long x,y;
	scanf("%lld%lld%lld",&n,&m,&k);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
	}
	for(int i=1;i<=n;i++)
	{
		f[i][0]=last[i]=b[a[i]^k];
		b[a[i]]=i;
	}
	l[0]=-1;
	p[0]=1;
	for(int i=1;i<=n;i++)l[i]=l[i/2]+1;
	for(int i=1;i<=20;i++)p[i]=p[i-1]*2;
	for(int i=1;i<=20;i++)
	{
		for(int j=1;j+p[i]-1<=n;j++)
		{
			f[j][i]=max(f[j][i-1],f[j+p[i-1]][i-1]);
		}
	}
	for(int i=1;i<=m;i++)
	{
		scanf("%lld%lld",&x,&y);
		if(dijah(x,y)>=x)printf("yes\n");
		else printf("no\n");
	}








  return 0;
}

posted @   dijah  阅读(112)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示