题面

给定一个长度为 \(n\) 的数列 \(A_{1}, A_{2}, \cdots, A_{n}\) 和一个非负整数 \(x\), 给定 \(m\) 次查询, 每次询问能否从某个区间 \([l, r]\) 中选择两个数使得他们的异或等于 \(x\)

对于所有评测用例, \(1 \leq n, m \leq 10^5,0 \leq x<2^{20}, 1 \leq l_{i} \leq r_{i} \leq n\)\(0 \leq A_{i}<2^{20}\)

思路

其实是一个 DP 题。

如果我们设 \(f_i\)\([1,i-1]\) 中存在 \(A_k \operatorname{xor} A_j\)\(\max(j,k)\)

如果设 \(L(i,k)\)\([1,i]\)\(k\) 最后出现的位置,那么动态转移方程就推出来了:

\[f_i=\max(f_{i-1},L(i,A_i\operatorname{xor} x)) \]

\(L\)std::map 实现,可以做到 \(O(n\log n)\)

最后回答询问的时候,只要判断 \(f_R \leq L\) 即可。因为如果满足 \(f_R\leq L\),那么肯定存在数对。

时间复杂度 \(O(n\log n+q)\)

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;

int n,m,x;
map<int,int> lst;
int f[100005];
int a[100005];

signed main(){
	cin>>n>>m>>x;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=n;i++){
		lst[a[i]]=i;
		f[i]=max(f[i-1],lst[a[i]^x]);
	}
	while(m--){
		int l,r;
		cin>>l>>r;
		cout<<(f[r]>=l?"yes":"no")<<'\n';
	}
	return 0;
}

原文地址:http://www.cnblogs.com/zheyuanxie/p/p8773.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性