AcWing 4645. 选数异或

文章介绍了AcWing上的一道中等难度的编程题,题目要求在给定的数列中,对每个查询区间判断是否存在两个不同下标的数,它们的异或值等于一个非负整数x。解决方案是通过预处理数列,使用动态规划方法记录每个位置右边最大能满足异或条件的下标,然后对每个查询区间判断是否存在满足条件的数对。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

AcWing 4645. 选数异或

原题

题目链接

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

输入格式

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

第二行包含 n 个整数 A1,A2,⋅⋅⋅,An 1, 2,···, 。

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

输出格式

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

数据范围

对于 20%20% 的评测用例,1≤n,m≤1001≤ , ≤100;
对于 40%40% 的评测用例,1≤n,m≤10001≤ , ≤1000;
对于所有评测用例,1≤n,m≤1000001≤ , ≤100000,0≤x<2200≤ <220,1≤li≤ri≤n1≤ ≤ ≤ ,0≤Ai<2200≤ <220。

输入样例:
4 4 1
1 2 3 4
1 4
1 2
2 3
3 3
输出样例:
yes
no
yes
no
样例解释

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

难度:中等
时/空限制:1s / 256MB
总通过数:4100
总尝试数:8669
来源:第十三届蓝桥杯省赛C++A/C/研究生组
算法标签

题解

#include<iostream>
#include<math.h>
using namespace std;
//  注意+的优先级大于移位的优先级
//  另外为了防止溢出一般设置的时候会多10个 
const int LAST=(1<<20)+10,F=100010;
int last[LAST]={0},f[F]={0};
int main()
{
//	输入 +获取last(一个下标是原始数,值是原始下标的数组) 
	int n,m,x;
	cin>>n>>m>>x;
	int a,l[m],r[m];
	for(int i=1;i<=n;i++)
	{
		cin>>a;
		f[i]=max(last[a^x],f[i-1]);
		last[a]=i;
	}
//	输入下标边界 
	for(int i=0;i<m;i++)
	{
		cin>>l[i];
		cin>>r[i];
	}
//	输出 
	for(int i=0;i<m;i++)
	{
		if(f[r[i]]>=l[i]) printf("yes\n");
		else printf("no\n");
	}	
} 

思路

参考闫总的视频

一一一一一一一一一一一一一一一一一一一一一一一一一一一→

​ ↑ ↑ ↑ ↑

​ L j i R

  • 1、看懂题目:l和r指的是下标,(可以看看下面l和r的取值范围理解)
  • 2、从r开始往左边遍历,对于遍历到的每个i,找到它左边(且离它最近的)的满足异或条件(A[i]A[j]=x→xA[i]=A[j])的最大下标j,只要能找到就是yes,如果不能找到满足条件的j则是no
  • 3、条件:因为i<r,所以j只需要大于L即可,因此i的范围可以推广至0<i<r,因为小于L部分的i找到的j不可能大于L(j在i的左边)
  • 4、所以,程序中,f[i]记录的是从1~i 的最大的j ,只要从下标为1~r的A[i]的异或值A[j]的下标j中最大的j 大于L即输出yes
  • 5、last记录的是值=A[…]的最大的从左边开始遍历原始数组到目前最大的下标
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值