【蓝桥杯每日一题】选数异或——线段树

server/2024/12/22 19:05:25/

选数异或

蓝桥杯每日一题 2024-12-16 选数异或 线段树 DP 思维

题目大意

给定一个长度为 n n n 的数组 A 1 , A 2 , ⋯ , A n A_1, A_2, \cdots, A_n A1,A2,,An 和一个非负整数 x x x,给定 m m m 次查询,每次询问能否从某个区间 [ l , r ] [l, r] [l,r] 中选择两个数使得它们的异或等于 x x x

解题思路

本题分三种解题方式:

1、小白暴力解法:直接在[l,r]区间内进行双重循环即可到手40分。

先了解下前提知识:a^b=x <==> a^x=b

2、思维大佬DP法: f(i) 表示 0 ~ i 之间的与 i 相距最近的那个满足 异或x后的值的下标;然后如果 f(i-1)满足条件,那么f(i)一定也满足件,那么状态转移方程就是: f ( i ) = m a x ( f ( i − 1 ) , l a s t ( a [ i ] ∗ x ) ) f(i) = max(f(i-1),last(a[i]*x)) f(i)=max(f(i1),last(a[i]x));最后判断的时候 f® 一定是0~r之前最大的满足条件的下标,那么只需要判断 其值是否大于L 即可。
为什么执着要判断 0~R 之间的,而不是LR之间的?因为在LR之间如果满足条件那么0~R一定会满足条件,那么这时候我们所要维护判断的边界只有左边界。

3、编程大佬线段树线段树的方法只是将DP法中的状态转移过程绕了一圈又回过来了。
也是先预处理每个位置的值所对应异或之后值的位置(都是左边的),然后线段树处理的是,每个区间的一个对应的最大值。要知道,这个最大值是一定小于它所在的下标的,所以说只需要处理找出最大值与左边界比较的结果即可。

40分暴力保分
#include <iostream>using namespace std;
typedef long long ll;
const int N = 100010;
int a[N];
int n,m;
int x;void sovle() {int l,r;cin>>l>>r;for(int i = l; i <= r;i++) {for(int j = i+1 ;j <= r;j++) {
//                cout<<"---> "<<a[i]<<" "<<a[j]<<" = "<<(a[i]^a[j])<<" "<<x<<endl;if((a[i]^a[j]) == x) {cout<<"yes"<<endl;return ;}}}cout<<"no"<<endl;
}int main()
{cin>>n>>m>>x;for(int i = 1;i <= n;i++) {cin>>a[i];}while(m--) {sovle();}return 0;
}
AC DP法
#include <bits/stdc++.h>using namespace std;const int N = 100010,M = 1 << 20;
int last[M],a[N];int main() {int n,m,x;cin>>n>>m>>x;for(int i = 1;i <= n;i++) {int t;cin>>t;// 一直递进更新,而且每次都是取得最大值a[i] = max(a[i-1],last[t^x]);last[t] = i;}while(m--) {int l,r;cin>>l>>r;// 这是a[r] 就代表着 r 前面所能够匹配的那些值的最大值if(a[r] >= l) puts("yes");else puts("no");}return 0;
}
AC 线段树
#include <iostream>using namespace std;const int N = 100010,M = (1 << 20)+10;
int a[N<<2],last[M],Left[N]; // a数组长度一定要扩大四倍
int n,m,x;void build(int u,int l,int r) {// 递归到叶子结点将所处理的位置更新到线段树if(l == r) {a[u] = Left[l];return ;}int mid = l + r >> 1;build(u<<1,l,mid);build(u<<1|1,mid+1,r);// 向上更新线段树 pushUp 操作a[u] = max(a[u<<1],a[u<<1|1]);
}int query(int u,int l,int r,int x,int y) {// 如果分后的区间被全包含,直接返回即可if(l >= x && r <= y) {return a[u];}int mid = l + r >> 1;// 第一种情况:找原始区间的左节点if(y <= mid) {return query(u<<1,l,mid,x,y);} else {/*** 第三种情况:*  l[________m_______]r*      x[____m_________]y * 这时候要将目标区间也分开来算,然后取他们的最大值即可**/if(x <= mid) return max(query(u<<1,l,mid,x,mid),query(u<<1|1,mid+1,r,mid+1,y));else return query(u<<1|1,mid+1,r,x,y);  // 第二种情况:找原始区间的右节点}
}int main() {cin>>n>>m>>x;for(int i = 1;i <= n;i++) {int t;cin>>t;// 预处理当前值所对应异或后的值的位置Left[i] = last[t ^ x];// 存储之前有的值,并存储索引last[t] = i;}// 建线段树build(1,1,n);while(m--) {int l,r;cin>>l>>r;// 在初始区间[1,n]中查找[l,r]中的所处理到的最大下标int k = query(1,1,n,l,r);// 判断这个最大下标是否在规定区间中if(k >= l) puts("yes");else puts("no");}return 0;
}
思考

这个题是比上一题好写一些的,但是思维难度是一点不减啊!!!

备注

想要一起备赛的同学可以评论区留言!


http://www.ppmy.cn/server/152301.html

相关文章

独孤思维:最近有新副业项目?

01 最近很多读者问我。 有没有新的项目&#xff1f; 其实独孤这边有一大把项目。 但是结合和他们的过往接触。 即便给他们了&#xff0c;他们也不会上手。 即便上手了&#xff0c;也不会坚持下去。 因为之前他们基本上没有做成过一个项目。 都是在不断找&#xff0c;不…

前端开放性技术面试—面试题

1. 上线出现问题如何解决&#xff1f; 步骤&#xff1a; 立即响应&#xff1a;迅速确认问题的存在和影响范围。回滚&#xff1a;如果问题严重影响用户&#xff0c;考虑立即回滚到上一个稳定版本。日志分析&#xff1a;查看服务器日志、应用日志和前端日志&#xff0c;定位问题…

黑客术语3

19、免杀 : 就是通过加壳、加密、修改特征码、加花指令等等技术来修改程序&#xff0c; 使其逃过杀毒软件的查杀。 20 、加壳 : 就是利用特殊的算法&#xff0c;将 EXE 可执行程序或者 DLL 动态连接库文件的 编码进行改变&#xff08;比如实现压缩、加密&#xff09;&a…

致远互联OA使用问题及解决方法记录(个人)

1、更换设备登录账号出现绑定要求 解决&#xff1a;后台管理员账号——M3安全管理——安全设置——删除绑定 2、审批消息错误回退 解决&#xff1a;协同工作——一已办事项——取回——重新审批/流程监督里撤回/流程索道节点回退 3、签章图片在表单上显示过大 解决&#x…

厦门凯酷全科技有限公司怎么样靠谱吗?

在数字经济蓬勃发展的今天&#xff0c;抖音电商以其独特的短视频和直播模式&#xff0c;迅速成为品牌与消费者之间的重要桥梁。作为一家专注于抖音电商服务的专业机构&#xff0c;厦门凯酷全科技有限公司凭借其深厚的技术实力、创新的服务模式和专业的团队支持&#xff0c;已经…

C语言进阶(2) ---- 指针的进阶

前言&#xff1a;指针的主题&#xff0c;我们在初阶的《指针》章节已经接触过了&#xff0c;我们知道了指针的概念&#xff1a; 1.指针就是个变量&#xff0c;用来存放地址&#xff0c;地址唯一标识一块内存空间。 2.指针的大小是固定的4/8个字节(32位平台/64位平台)。 3.指针是…

【自用】通信内网部署rzgxxt项目_01,后端pipeDemo部署(使用nssm.exe仿照nohup)

做完这些工作之后&#xff0c;不要忘记打开 Windows Server 的防火墙端口&#xff0c;8181、8081、8080、22、443、1521 做完这些工作之后&#xff0c;不要忘记打开 Windows Server 的防火墙端口&#xff0c;8181、8081、8080、22、443、1521 做完这些工作之后&#xff0c;不要…

cenos如何升级git到2以上版本

1&#xff1a;先卸载旧的版本: # 卸载源默认安装的git $ git --version git version 1.8.3.1 $ sudo yum remove git2: 安装新的git版本 编译 配置环境变量 下载相关依赖 并安装 [rootlocalhost /]# yum install curl-devel expat-devel openssl-devel zlib-devel gcc […