异或基本运算规律和dp简单使用
递推优化
不妨将满足题意的两个数a, b简称为数对, a、b中较小的下标叫下界.
定义dp[i]为[1, i]区间中所有数对中的最大下界
如样例1 2 3 4, 只有2 3的异或为1.
对于区间[1, 2]它不包含数对{2, 3}所以dp[2]应该为一个无效值, 取0
对于区间[1, 3] [1, 4], 都仅且包含数对{2, 3}, 所以dp[3] = dp[4] = 2
dp[r]的实际意义想必大家都看出来了, 就是当查询区间[l, r], 右边界为r时, 至少包含一个数对时的左边界最大值, 所以如果l小于等于这个左边界最大值, [l, r]区间内就至少有一个数对。
代码实现
用哈希表mp[x]记录数值X最后一次出现时的位置下标, dp[i]的求法是: 若ai⊕xai⊕x最后一次出现的下标要大于dp[i-1], 则dp[i] = mp[ai⊕x], 否则dp[i] = dp[i-1]
即
dp[i]=max(dp[i−1],mp[ai⊕x])
dp[i]=max(dp[i−1],mp[ai⊕x])
时间复杂度: O(n)
#include<iostream>
using namespace std;
#include<map>
#define endl "\n"
#pragma GCC optimize(3)
int dp[1000010];
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int n,m,x;
map<int,int> mp;
cin>>n>>m>>x;
for(int i=1;i<=n;i++)
{
int a;cin>>a;
dp[i]=max(dp[i-1],mp[x^a]);
mp[a]=i;
}
for(int i=1;i<=m;i++)
{
int l,r;
cin>>l>>r;
cout<<(dp[r]>=l?"yes":"no")<<endl;
}
return 0;
}

浙公网安备 33010602011771号