题目描述
题解
对于异或运算,我们有如下数学性质:若$$a\bigoplus b=x$$则有$$a\bigoplus x=b$$或$$b\bigoplus x = a$$
另外,异或运算也满足交换律和结合律。对于一个整数 \(a\) ,有且只存在一个数 \(b\) 使得 \(a\bigoplus b=x\),我们可以通过 \(a\bigoplus x\) 来得到这个数 \(b\).
对于满足\(a\bigoplus b=x\) 的 \(<a, b>\),我们称之为合法组合。定义 \(f(i)\) 为 \([0,i]\) 内所有合法组合中 \(a\) 的最大下标。
对于问询区间 \([l,r]\), 我们只需考虑是否存在一个合法组合 \(<a,b>\) 位于该区间内。当我们查询 \(f(r)\)时, 默认 \(b\) 位于该区间内,这时若 \(f(r) \ge l\),就能保证 \(a\) 也位于区间内,此时就可以输出yes
,反之输出no
。
定义一个hashTable
,对于当前的数列值 \(b\) 和 下标 \(i\),若哈希表中不存在 \(x \bigoplus b\),则\(f(i)=f(i-1)\),反之 \(f(i)=max(f(i-1),hashTable[x \bigoplus b])\). 对于 \(C++\) 中的 map
,当查询的key
不存在时,其值为0,综上,状态转移方程为:$$f(i)=max(f(i-1),hashTable[x \bigoplus b])$$
代码:
#include <iostream>
#include<map>
#include<algorithm>
using namespace std;
const int N = 100005;
int f[N];
int n, m, x;
map<int, int> mp;
void solve();
int main()
{
ios_base :: sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
while (t--)
{
solve();
}
return 0;
}
void solve()
{
cin >> n >> m >> x;
int v;
for(int i = 1; i <= n; i++)
{
cin >> v;
f[i] = max(f[i - 1], mp[v^x]);
mp[v] = i;
}
int l, r;
for(int i = 0; i < m; i++)
{
cin >> l >> r;
if(f[r] >= l) cout << "yes" << endl;
else cout << "no" << endl;
}
}