当前位置: 首页 > article >正文

选数异或 (AcWing 4645)

题目链接: https://www.acwing.com/problem/content/description/4648/

题目描述:

评价: 这道题感觉还是蛮有意思的,难度适中,而且有一定的思维含量,值得反复品味。

思路: 首先我们定义一个数组g[N], 其中的每个元素g[i] 表示在所有 i<j<=n 的j中,满足a[j] ^ a[i] = x的最小的那个j.  这是因为如果存在多个这样的j, 最小的那个j一定是最优的,因为他更加容易被包含在一个区间[l,r] 中. 

假设我们已经得到了上面的数组g, 那么实际上题目的问题就转化为: 每次给定一个查询[l,r] ,询问所有 l=< i <=r 的 i 是否存在一个g[i] <= r. 进一步,我们将这个问题转化为:

询问数组g在区间[l,r] 上的最小值是否小于等于r. 这是一个区间查询问题,且这个问题是满足区间可加性的,可以用线段树解决。

那么只需要考虑数组g 是如何构建的,注意到,若给定a, 满足 a^b=c 的b的取值是唯一的(等式两边异或上a就不难证明),因此,对于每一个位置i,满足t ^ a[i] =x 的值t是唯一的,我们只需要知道数组中数值 t 出现的全部位置即可; 另一方面,由于数组g的定义,因此需要动态维护每个数值出现的索引(要保证后面的位置不能够使用前面的位置的信息),因此可以用一个队列(先进先出)来进行维护。

参考代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<unordered_map>
#define ll long long
using namespace std;
const int N=1e5+10;
const int inf=1e9+7;
int n,m,x;
int a[N];
int g[N];
unordered_map<int,int> hashs;
queue<int> q[N];
int cnt=0;

struct node{
	int l;
	int r;
	int minnum;
};
node tree[4*N];
void push_up(int cur){
	tree[cur].minnum=min(tree[cur<<1].minnum,tree[cur<<1|1].minnum);
	return ;
}
void build(int cur,int l,int r){
	tree[cur].l=l;
	tree[cur].r=r;
	if(l==r) {
		tree[cur].minnum=g[l];
		return ;
	}
	int mid=l+r>>1;
	build(cur<<1,l,mid);
	build(cur<<1|1,mid+1,r);
	push_up(cur);
	return ;
}

int gets(int cur,int l,int r){
	if(tree[cur].l>=l&&tree[cur].r<=r){
		return tree[cur].minnum;
	}
	int mid=tree[cur].l+tree[cur].r>>1;
	int res1=inf;
	int res2=inf;
	if(l<=mid) res1=gets(cur<<1,l,r);
	if(r>=mid+1) res2=gets(cur<<1|1,l,r);
	int res=min(res1,res2);
	return res;
}

int main(void){
	
	scanf("%d%d%d",&n,&m,&x);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		if(hashs[a[i]]==0){
			hashs[a[i]]=++cnt;
		}
		q[hashs[a[i]]].push(i);
	}
	for(int i=1;i<=n;i++){
		int tmp=x^a[i];
		q[hashs[a[i]]].pop();
		if(hashs[tmp]==0) g[i]=n+1;
		else{
			if(q[hashs[tmp]].empty()) g[i]=n+1;
			else 
			g[i]=q[hashs[tmp]].front();
		}
		
	}
	build(1,1,n);
	for(int i=1;i<=m;i++){
		int l,r;
		scanf("%d%d",&l,&r);
		int res=gets(1,l,r);
		if(res<=r) printf("yes\n");
		else printf("no\n");
	}
	
	return 0;
}


http://www.kler.cn/news/274787.html

相关文章:

  • 设计模式学习笔记 - 规范与重构 - 8.实践:程序出错返回啥?NULL、异常、错误吗、空对象?重构ID生成器,处理各函数的异常
  • 国内外15款AI搜索引擎汇总
  • 选择排序算法(Selection Sort)原理及实现
  • 基于Spring Boot+Vue的智慧图书管理系统
  • 【使用xlrd、xlutils读写excel】
  • Devops-01-devops 是什么?
  • 自动化单元测试 Automatic Test Generation
  • 漫谈微服务网关
  • 性能优化(CPU优化技术)-NEON指令详解
  • 服务器版本命令查看
  • Http的缓存有哪些
  • 前端项目,个人笔记(五)【图片懒加载 + 路由配置 + 面包屑 + 路由行为修改】
  • k8s详细教程
  • QT 驾校系统界面布局编写
  • ES集群和分片以及脑裂
  • 竞争优势:大型语言模型 (LLM) 如何重新定义业务策略
  • DOM节点操作
  • LVGL:拓展部件——键盘 lv_keyboard
  • Spring MVC入门(4)
  • WPF —— 控件模版和数据模版