NOIP集训 P4137 Rmq Problem / mex 题解
前置指使:可持久化线段树
题解:P4137 Rmq Problem / mex
有一个长度为 \(n\) 的数组 \(\{ a_1,a_2,...,a_n \}\) 。
\(m\) 次询问,每次询问一个区间内最小没有出现过的自然数。
Input
第一行,两个正整数 \(n,m\) 。
第二行,\(n\) 个非负整数 \(a_1, a_2,...,a_n\) 。
接下来 \(m\) 行,每行两个正整数 \(l,r\),表示一次询问。
Output
输出 \(m\) 行,每行一个数,依次表示每个询问的答案。
Note
对于 \(100\%\) 的数据:\(1\le n,m\le 2e5, 1\le l\le r\le n,0\le a_i\le 2e5\)。
分析
思考 \(mex\) 的本质。对于一段给定的区间,\(mex\) 即是从 \(0\) 开始存在的连续值域的最大值加 \(1\)。若 \(0\) 不在区间值域中则 \(mex\) 为 \(0\)。
在值域线段树上考虑问题。序列中的值暂时不用考虑,因为可以二分值域直接处理。对于 \([l,r]\) 的 \(mex\) ,即是要在 \(r\) 这棵树上找到一个最小的 \(i\) ,使得这个 \(i\) 上次出现的位置 \(last_i\) 小于 \(l\)。
所以可以在主席树上维护每个值出现位置的 \(min\),注意加入时要把 \(x\) 加上 \(1\) ,再在查询时减去 \(1\) 防止值域出现问题.
数据不需要离散化。同时,对于大于 \(n\) 的 \(a_i\) 显然对答案没有任何贡献,因为这时必然存在一个小于等于 \(n\) 的 \(mex\)。
AC代码:
#include<bits/stdc++.h>
using namespace std;
inline int read() {
int f = 1, otto = 0;
char a = getchar();
while(!isdigit(a)) {
if(a == '-') f = -1;
a = getchar();
}
while(isdigit(a)) {
otto = (otto << 1) + (otto << 3) + (a ^ 48);
a = getchar();
}
return f * otto;
}
const int maxn = 2e5 + 10;
int ver;
int rt[maxn], tr[maxn << 5], ls[maxn << 5], rs[maxn << 5];
void upd(int &u1, int u2, int l, int r, int num, int loc) {
if(!u1) u1 = ++ver;
if(l == r) return tr[u1] = loc, void(0);
int mid = l + r >> 1;
if(num <= mid) rs[u1] = rs[u2], upd(ls[u1], ls[u2], l, mid, num, loc);
else ls[u1] = ls[u2], upd(rs[u1], rs[u2], mid + 1, r, num, loc);
return tr[u1] = min(tr[ls[u1]], tr[rs[u1]]), void(0);
}
int ask(int u, int l, int r, int lim) {
if(l == r) return l;
int mid = l + r >> 1;
if(tr[ls[u]] < lim) return ask(ls[u], l, mid, lim);
else return ask(rs[u], mid + 1, r, lim);
}
int main() {
int n = read() + 1, m = read();
for(int i = 1; i < n; i++) {
int x = read() + 1;
if(x > n) rt[i] = rt[i - 1];
else upd(rt[i], rt[i - 1], 1, n, x, i);
}
while(m--) {
int l = read(), r = read();
printf("%d\n", ask(rt[r], 1, n, l) - 1);
}
return 0;
}
小结:
对于类似的题套路性很强,但是转化具有一定的思维难度。要多做题,多见题才更能掌握主席树的应用。
NOIP集训 P4137 Rmq Problem / mex 题解的更多相关文章
- 洛谷 P4137 Rmq Problem/mex 题解
题面 首先,由于本人太菜,不会莫队,所以先采用主席树的做法: 离散化是必须环节,否则动态开点线段数都救不了你: 我们对于每个元素i,插入到1~(i-1)的主席树中,第i颗线段树(权值线段树)对于一个区 ...
- P4137 Rmq Problem / mex (莫队)
题目 P4137 Rmq Problem / mex 解析 莫队算法维护mex, 往里添加数的时候,若添加的数等于\(mex\),\(mex\)就不能等于这个值了,就从这个数开始枚举找\(mex\): ...
- 主席树||可持久化线段树+离散化 || 莫队+分块 ||BZOJ 3585: mex || Luogu P4137 Rmq Problem / mex
题面:Rmq Problem / mex 题解: 先离散化,然后插一堆空白,大体就是如果(对于以a.data<b.data排序后的A)A[i-1].data+1!=A[i].data,则插一个空 ...
- 洛谷 P4137 Rmq Problem /mex 解题报告
P4137 Rmq Problem /mex 题意 给一个长为\(n(\le 10^5)\)的数列\(\{a\}\),有\(m(\le 10^5)\)个询问,每次询问区间的\(mex\) 可以莫队然后 ...
- 【luogu P4137 Rmq Problem / mex】 题解
题目链接:https://www.luogu.org/problemnew/show/P4137 求区间内最大没出现过的自然数 在add时要先判断会不会对当前答案产生影响,如果有就去找下一个答案. # ...
- 洛谷 P4137 Rmq Problem / mex
https://www.luogu.org/problemnew/show/P4137 只会log^2的带修主席树.. 看了题解,发现有高妙的一个log做法:权值线段树上,设数i对应的值ma[i]为数 ...
- P4137 Rmq Problem / mex
目录 链接 思路 线段树 莫队 链接 https://www.luogu.org/problemnew/show/P4137 思路 做了好几次,每次都得想一会,再记录一下 可持久化权值线段树 区间出现 ...
- luogu P4137 Rmq Problem / mex 主席树 + 思维
Code: #include<bits/stdc++.h> #define maxn 200001 using namespace std; void setIO(string s) { ...
- Luogu P4137 Rmq Problem / mex
区间mex问题,可以使用经典的记录上一次位置之后再上主席树解决. 不过主席树好像不是很好写哈,那我们写莫队吧 考虑每一次维护什么东西,首先记一个答案,同时开一个数组记录一下每一个数出现的次数. 然后些 ...
- 洛谷P4137 Rmq Problem / mex(莫队)
题目描述 有一个长度为n的数组{a1,a2,…,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. 输入输出格式 输入格式: 第一行n,m. 第二行为n个数. 从第三行开始,每行一个询问l, ...
随机推荐
- Kyuubi支持Iceberg配置
一.简述 Kyuubi调用Spark来查询iceberg表,修改Spark配置信息即可. 二.服务配置 1.上传jar包到Kyuubi server节点 可以选择emr spark组件后,按照配置组( ...
- mac安装gcc7
查看gcc版本 gcc --version 1.安装gcc brew install gcc@7 cd /usr/local/Cellar 改名mv gcc\@7/ gcc 2.打开mac的SIP ...
- 【忍者算法】从十字路口相遇到链表交点:探索相交链表问题|LeetCode第160题 相交链表
从十字路口相遇到链表交点:探索相交链表问题 生活中的相遇问题 想象两个人从不同的地方出发,最后在一个十字路口相遇.他们可能走过不同长度的路程,但最终会在同一个点汇合.这就很像我们今天要讨论的相交链表问 ...
- 洛谷P2789 直线交点数 题解
解题思路 考虑将直线分组,每组内直线互相平行,任意两组直线间交点数量等于两组内直线数量乘积. 分组操作使用dfs,求出交点数量后加入set去重,输出set大小. 时间复杂度O(2NN2)有点鬼畜但是可 ...
- STM32 DMA操作
https://blog.csdn.net/u014754841/article/details/79525637?utm_medium=distribute.pc_relevant.none-tas ...
- copilot插件使用介绍
Copilot插件是一个由GitHub开发的人工智能代码助手,可以为开发人员提供代码自动补全和建议功能.Copilot使用了机器学习技术,通过分析大量的开源代码来自动生成代码片段和建议. 使用Copi ...
- Nginx - [02] 安装部署&配置
官网下载地址:http://nginx.org/en/download.html 001 || 安装[windows] 解压之后,在命令提示符窗口启动nginx.exe 在浏览器访问80端口:loca ...
- Flink运行时架构
一.运行时的组件和基本原理 1.作业管理器 (1)控制一个应用程序执行的主进程,也就是说,每个应用程序都会被一个不同的JobManager所控制执行. (2)JobManager会先接收到要执行的应用 ...
- python excel 打开表格:表格名不知道应该怎么打开
取所有表格名的倒数第一个就是操作的表格 import pandas as pd xl = pd.ExcelFile(xlPath) names = xl.sheet_names df = xl.par ...
- 附035.Kubernetes_v1.25.3高可用部署架构二
目录 部署组件 kubeadm介绍 kubelet介绍 kubectl介绍 方案概述 方案介绍 部署规划 节点规划 主机名配置 变量准备 互信配置 环境初始化 部署高可用组件 HAProxy安装 Ke ...