【蓝桥每日一题]-动态规划 (保姆级教程 篇8)#选数异或

目录

题目:选数异或

  思路:


  

题目:选数异或

题意:一个大小n的数组中进行m次查询,每次查询下标[l,r]区间有没有异或后是X的,有则对这个区间输出yes,没有输出no。  (数据范围忘了,不过你暴力搜索的话不可能过,这你放心

  

思路:

首先你要知道异或运算的性质:  异或运算^   性质:a^b=c则a=c^b(我喜欢称a和b是对象关系哦,下面都称为对象关系了)

   

我们设置dp[i]表示以i为右端点开始,存在有对象的元素的最小左下标(dp[i]就是这个下标),即最小满足(题意)区间。只要以r为右端点的查询区间的左端点比这个dp[r]小就一定有解 


转移方程:dp[i]=max(dp[i-1],a[i]^x的下标):在这个区间中,a[i]的对象若比a[i-1]的对象远,那就取a[i-1]对象的位置; 但是在i右边的对象一律不管!

  

然后你就会发现这其实是一类题,任何两个有关系的数(对象关系),然后问查询区间,都可以用这种思想 

  

#include  
using namespace std;
int a[100002],dp[100002],pos[1210000];
int main(){//dp[i]表示以i为右边界的最左下标对应的最优解   pos记录每个元素的下标
	int n,m,x;cin>>n>>m>>x;
	for(int i=1;i<=n;i++) {
		scanf("%d",&a[i]);
	}
	for(int i=1;i<=n;i++){
		pos[a[i]]=i; //注意!!!pos初始化必须在这个循环中写,因为在i右边的对象一律不管
		dp[i]=max(dp[i-1],pos[a[i]^x]); //a[i]对象元素太远了,就用上一组对象呗
	}
	while(m--){
		int l,r;
		scanf("%d %d",&l,&r);
		if(dp[r]>=l)cout<<"yes"<<'\n';
		else cout<<"no"<<'\n';
	}
}


你可能感兴趣的:(算法,动态规划)