追星赶月莫停留,平芜尽处是春山|

CheZiHe929

园龄:1年10个月粉丝:9关注:4

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

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

题目链接

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

简要思路

题目让我们查询是否有两个数 a,b 满足 ab=x,根据异或的性质,我们可以将上式转换为 b=ax,因此对于每一个 ai,我们只需查询在 [l,r] 的区间内,是否有一个值为 aix 的数 b

每一次遍历整个区间肯定是会超时的,所以我们考虑优化。

维护两个“数组”:

fi 代表到 i 这个位置,前面满足 ab=x 的二元组 (a,b) 中最前面的一个数的位置,没有的默认为 0(即到 i 这个位置,前面最少要到那个位置才有二元组)。

lasi 代表 i 出现的最后一个位置,没有的话也是默认为 0

但是注意到:0x<220,0Ai<220,所以我们的 las 就要用 map 来维护。

对于 fi 的转移,一共分为两种情况:

当当前输入的这个数 a 不会产生新的满足条件的二元组或产生的位置太靠前时,答案就为 fi1,否则答案为 lasax(根据异或的性质所得),所以我们只需对这两个数取 max,得到较后的数即可。

考虑查询。

查询就很简单了,对于一个 r,我们只需查询 fr 是否 l 即可(即查看以 r 结尾的区间,前面最后出现的满足条件的值的位置是否在 l 后面,也就是查看 [l,r] 这个区间是否包括符合答案的区间)。

完整代码

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
const int MAXN=1e5+5;
int n,m,x,a;
int f[MAXN];//f[i] 以 i 结尾上一个满足条件的值的位置
std::map<int,int> las;//las[i] 上一个值为 i 的位置
signed main(){
std::cin>>n>>m>>x;
for(int i=1;i<=n;i++){
std::cin>>a;
f[i]=std::max(f[i-1],las[a^x]);//维护
las[a]=i;//更新最后出现的位置
}
while(m--){
int l,r;
std::cin>>l>>r;
if(f[r]>=l)std::cout<<"yes\n";
else std::cout<<"no\n";//查询
}
return 0;
}
posted @   CheZiHe929  阅读(158)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起