选数异或2022年蓝桥杯

题目

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

输入格式

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

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

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

输出格式

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

数据范围

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

输入样例:

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

输出样例:

yes
no
yes
no

解题思路

1、关于异或

a ⊕ b = c ⟺ a ⊕ c = b

因此对于一个数a,其对应的数可以直接计算得出,即为a⊕x

 2、动态规划数组含义

将两个配对的数a,b简称为数对

定义dp[i]为区间[1,i]中所有数对中的最大下界

当查询区间[l,r]右边界为r时,至少包含一个数对时的左边界最大值,所以如果l小于左边界最大值(dp[r]),[l,r]内至少有一个数对

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n, m, x;
int dp[N];
unordered_map<int, int> last;
int main() {
	cin >> n >> m >> x;
	for (int i = 1, a; i <= n && cin >> a; ++ i) {
		dp[i] = max(dp[i - 1], last[a ^ x]);
		last[a] = i;
	}
	while (m -- ) {
		int l, r;
		cin >> l >> r;
		cout << (dp[r] >= l ? "yes" : "no") << endl;
	}
}

本篇博客代码主要参考于文章:

4645. 选数异或 (syrr.cn)

猜你喜欢

转载自blog.csdn.net/m0_52124992/article/details/129840556
今日推荐