思路:
首先可以预处理前缀和𝑠快速计算区间异或.
如果整段异或和为0,随便分成两部分都是正确的.
否则我们至少需要分成3段,设整段异或和为 𝑘.
所以我们需要找到一个位置满足 𝑠𝑥⊕𝑠𝑙−1=𝑘 ,然后我们需要在𝑥后面找到一个位置满足 𝑠𝑦⊕𝑠𝑙−1=0.
可以把数字分桶存储然后二分找到符合要求的位置.
代码:
cpp
#include<iostream>
#include<cstring>
#include<vector>
#include<map>
using namespace std;
using LL = long long;
int main(){
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
int T;
cin >> T;
while(T--){
int n, m;
cin >> n >> m;
vector<int> a(n + 1);
map<int, vector<int> > mp;
for(int i = 1; i <= n; i++){
cin >> a[i];
a[i] ^= a[i - 1];
mp[a[i]].push_back(i);
}
while(m--){
int l, r;
cin >> l >> r;
if ((a[l - 1] ^ a[r]) == 0){
cout << "YES" << '\n';
continue;
}
auto &v1 = mp[a[r]];
auto it = lower_bound(v1.begin(), v1.end(), l); // 找到x,a[x] ^ a[l - 1] = k
if (it == v1.end() || *it >= r){
cout << "NO" << '\n';
continue;
}
int pos = *it;
auto &v2 = mp[a[l - 1]];
auto nit = lower_bound(v2.begin(), v2.end(), pos + 1); // 找到y,a[y] ^ a[l - 1] = 0
if (nit != v2.end() && *nit < r){
cout << "YES" << '\n';
}
else{
cout << "NO" << '\n';
}
}
cout << '\n';
}
}