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, ...
随机推荐
- Linux驱动---LED
目录 一.pinctrl子系统 二.GPIO子系统 三.GPIO操作步骤 3.1.获取GPIO描述符 3.2.设置方向 3.3.读写值 四.编写LED驱动 4.1.硬件原理图 4.2.修改设备树 4. ...
- flutter-超出部分隐藏
第一种写法 1 ConstrainedBox( 2 constraints: BoxConstraints( 3 maxHeight: 100 4 ), 5 child: Stack( 6 overf ...
- 清华大学推出第三讲普通人如何抓住 DeepSeek 红利,普通人必备的免费AI手册!
前言 在当今这个日新月异的时代,人工智能(AI)技术正以前所未有的速度改变着我们的生活.工作和社会结构.从智能手机上的语音助手到自动驾驶汽车,从医疗诊断到学术研究,AI的应用无处不在,它如同一股不可阻 ...
- Refit 原理解析:从初识到实践
在现代的分布式系统和微服务架构中,HTTP API 调用是不可或缺的一部分.为了简化 HTTP 请求的构建和解析,我们可以使用 Refit 这个强大的库.Refit 通过将 HTTP API 抽象为接 ...
- rabbitmq的基本使用
使用MQ的三大作用:1.同步变异步2.流量削峰3.解耦降低服务间的耦合性要不要使用MQ,需不需要使用MQ依据项目的需要做选择. 使用场景: 例如:注册用户时候,发送激活邮件.监控应用中抛出的异常,邮件 ...
- pandas 判断列是否包含某个字符串
亲测第二种好用 in 语句 不包含使用not in food = df['日期'].values.tolist() if '休息' in food: print(food) if df['共计小时'] ...
- MySQL 常用优化
目录 单表优化 字段 索引 查询SQL 引擎 MyISAM InnoDB 系统调优参数 升级硬件 读写分离 缓存 表分区 分区的好处是: 分区的限制和缺点: 分区的类型: 分区适合的场景有: 垂直拆分 ...
- Wireshark 的过滤器类型
Wireshark 是一个强大的网络协议分析工具,支持多种类型的过滤器来帮助用户捕获和分析网络流量. 根据使用场景和功能,Wireshark 的过滤器可以分为以下两类: 1. 捕获过滤器(Captur ...
- .NET 10 Preview 2 增强了 Blazor 和.NET MAUI
.NET 团队 3.18 发布了.NET 10 Preview 2(https://devblogs.microsoft.com/dotnet/dotnet-10-preview-2/)..NET 1 ...
- 详细讲述了CPU的调度原理,本篇讲一下内存的分配过程。
运行在ESXi主机上的虚拟机分配内存之和可以超过物理机的实际内存大小,这个技术叫做超额分配(overcommitment),即使单个虚拟机的内存分配值都可以超分.但是超分的结果就是可能会引起内存资源竞 ...