出来混,总要还的。
题目
给定一个长度为 nn 的数列 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<2^20,1≤li≤ri≤n,0≤Ai<2^20。
样例
题解
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010, M = (1 << 20) + 10;
int n, m, x;
int last[M], g[N];
int main()
{
scanf("%d%d%d", &n, &m, &x);
for (int i = 1; i <= n; i ++ )
{
int a;
scanf("%d", &a);
g[i] = max(g[i - 1], last[a ^ x]);
last[a] = i;
}
while (m -- )
{
int l, r;
scanf("%d%d", &l, &r);
if (g[r] >= l) puts("yes");
else puts("no");
}
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
using namespace std;
const int N = (1 << 20) + 10, M = 100010;
int g[M] = { 0 }, last[N] = { 0 };
int main() {
int m, n, x;
cin >> n >> m >> x;
for (int i = 1; i <= n; i++)
{
int a; cin >> a;
g[i] = max(g[i - 1], last[a ^ x]);
last[a] = i;
}
while(m--)
{
int l, r;
cin >> l >> r;
if (g[r] >= l)cout << "yes" << endl;
else cout << "no" << endl;
}
}
注意事项
a^b=x则a=b^x。
1<<20表示在二进制中将1左移20为,即2^20。
g[i]表示离第i个数最近的能取到一对满足情况的数所需的l的最大值。
last[a]=i表示第i个数的数值是a,这样处理便于求g[i]。
对于第13,14行代码的顺序不能颠倒,原因如下:last[a] = i在前面的话,当x为0时,a ^ x等于a, 这个时候last[a ^ x] = last[a] = i,这个时候last未被更新为小于i即合法数据,不能参与运算,所以更新last[a]应该在后面。