选数异或-acwing每日一题

12 篇文章 0 订阅
9 篇文章 0 订阅

项目场景:

较难的dp+哈希 思维题


问题描述

给定一个长度为 n 的数列 A1,A2,···,An 和一个非负整数 x,给定 m 次查询,每次询问能否从某个区间 [l,r] 中选择两个数使得他们的异或等于 x。

输入格式

输入的第一行包含三个整数n,m,x。

第二行包含 n 个整数 A1,A2,···,An。

接下来 m 行,每行包含两个整数 li,rili,ri 表示询问区间 [li,ri][li,ri]。

输出格式

对于每个询问,如果该区间内存在两个数的异或为 x 则输出 yes,否则输出 no

数据范围

对于 20% 的评测用例,1≤n,m≤100;
对于 40% 的评测用例,1≤n,m≤1000;
对于所有评测用例,1≤n,m≤100000,0≤x<220,1≤li≤ri≤n,0≤Ai<220。

输入样例:

4 4 1
1 2 3 4
1 4
1 2
2 3
3 3

输出样例:

yes
no
yes
no

样例解释

显然整个数列中只有 2,3 的异或为 1。


原因分析:

题目是在指定的一段区间内判断区间内是否存在一个数与指定的数异或的值为x

考虑dp f[i] 存储的为与a[i]异或的数的下标值 区间为[l,r]  l<=i<=r l<=f[i]<i<=r 要满足题目要求 则判断f[r]与l的关系即可 只要保证f[r]>=l 则一定存在匹配 具体见代码

 


实现代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<unordered_map>
using namespace std;
const int N = 1e6+10;
int f[110];
int a[N];
int n,m,x;
unordered_map<int,int> last;

int main(){
    //读入数据部分
    cin>>n>>m>>x;
    for(int i=1;i<=n;i++) cin>>a[i];

    //进行dp
    //这里的f[i] 表示与a[i]匹配的最近的数的下标
    //last[a[i]^x] 表示与a[i]匹配的数最后一次出现的下标
    for(int i=1;i<=n;i++){
        f[i] = max(f[i-1],last[a[i]^x]);
        last[a[i]] = i;
    }

    while(m--){
        int l,r;
        cin>>l>>r;
        //只需要区间的右端点对应的f[i]存储的下标大于左端点 则说明在指定区间内存在一个数能够与给定数匹配
        if(f[r]>=l) cout<<"yes"<<endl;
        else cout<<"no"<<endl;
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值