异或基本运算规律和dp简单使用

 题目:4645. 选数异或 - AcWing题库

 

递推优化
不妨将满足题意的两个数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;
   }

 

posted @ 2023-01-02 22:07  七星,北辰  阅读(121)  评论(0)    收藏  举报