前置指使:可持久化线段树

题解: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 题解的更多相关文章

  1. 洛谷 P4137 Rmq Problem/mex 题解

    题面 首先,由于本人太菜,不会莫队,所以先采用主席树的做法: 离散化是必须环节,否则动态开点线段数都救不了你: 我们对于每个元素i,插入到1~(i-1)的主席树中,第i颗线段树(权值线段树)对于一个区 ...

  2. P4137 Rmq Problem / mex (莫队)

    题目 P4137 Rmq Problem / mex 解析 莫队算法维护mex, 往里添加数的时候,若添加的数等于\(mex\),\(mex\)就不能等于这个值了,就从这个数开始枚举找\(mex\): ...

  3. 主席树||可持久化线段树+离散化 || 莫队+分块 ||BZOJ 3585: mex || Luogu P4137 Rmq Problem / mex

    题面:Rmq Problem / mex 题解: 先离散化,然后插一堆空白,大体就是如果(对于以a.data<b.data排序后的A)A[i-1].data+1!=A[i].data,则插一个空 ...

  4. 洛谷 P4137 Rmq Problem /mex 解题报告

    P4137 Rmq Problem /mex 题意 给一个长为\(n(\le 10^5)\)的数列\(\{a\}\),有\(m(\le 10^5)\)个询问,每次询问区间的\(mex\) 可以莫队然后 ...

  5. 【luogu P4137 Rmq Problem / mex】 题解

    题目链接:https://www.luogu.org/problemnew/show/P4137 求区间内最大没出现过的自然数 在add时要先判断会不会对当前答案产生影响,如果有就去找下一个答案. # ...

  6. 洛谷 P4137 Rmq Problem / mex

    https://www.luogu.org/problemnew/show/P4137 只会log^2的带修主席树.. 看了题解,发现有高妙的一个log做法:权值线段树上,设数i对应的值ma[i]为数 ...

  7. P4137 Rmq Problem / mex

    目录 链接 思路 线段树 莫队 链接 https://www.luogu.org/problemnew/show/P4137 思路 做了好几次,每次都得想一会,再记录一下 可持久化权值线段树 区间出现 ...

  8. luogu P4137 Rmq Problem / mex 主席树 + 思维

    Code: #include<bits/stdc++.h> #define maxn 200001 using namespace std; void setIO(string s) { ...

  9. Luogu P4137 Rmq Problem / mex

    区间mex问题,可以使用经典的记录上一次位置之后再上主席树解决. 不过主席树好像不是很好写哈,那我们写莫队吧 考虑每一次维护什么东西,首先记一个答案,同时开一个数组记录一下每一个数出现的次数. 然后些 ...

  10. 洛谷P4137 Rmq Problem / mex(莫队)

    题目描述 有一个长度为n的数组{a1,a2,…,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. 输入输出格式 输入格式: 第一行n,m. 第二行为n个数. 从第三行开始,每行一个询问l, ...

随机推荐

  1. Python实战:为Prometheus开发自定义Exporter

    Python实战:为Prometheus开发自定义Exporter 在当今的微服务架构和容器化部署环境中,监控系统的重要性不言而喻.Prometheus作为一款开源的系统监控和警报工具,以其强大的功能 ...

  2. Python 合并 Excel 单元格

    合并 Excel 单元格是 Excel 数据处理和表格设计中的一项常用操作.例如,在制作表格标题时,经常会将多个单元格合并,使标题能够跨列显示,更加醒目和美观.此外,当对数据进行分类时,为了使同一类别 ...

  3. Android开发之定时任务(AlarmManager、WorkManager)

    Android 程序的定时任务主要有AlarmManager.WorkManager两种. 一.AlarmManager AlarmManager,又称闹钟,可以设置一次性任务,周期重复任务,定时重复 ...

  4. macbookpro m3本地部署DeepSeek模型

    macbookpro m3有着十分强大的性能.在deepseek如火如荼的当下,可以尝试在本地部署并使用.还可以将自己的文档作为语料喂给deepseek,使其能成为自己专属的AI助手. 本文介绍使用o ...

  5. Typecho博客优化,利用MyUpload进行图片压缩

    写博客时,如果不压缩图片,既比较费主机存储空间,还会非常拖慢页面加载速度,特别是对于带宽小的主机.可是,如果要压缩好图片后再上传又比较麻烦,放到对象存储上还另外要钱.于是乎,就撸了这个插件,在上传时自 ...

  6. C# 图形界面编程之 FlowLayoutPanel 界面闪烁问题解决

    公司需要我写几个GUI程序,让虚拟机(guest)内部可以控制虚拟机(host)外部的硬件. 控制外部的硬件的方法就是开一个串口,这样虚拟机与宿主机就可以相互通讯,此时就可以让虚拟机发送命令,宿主机执 ...

  7. .net core 非阻塞的异步编程 及 线程调度过程

    本文主要分为三个部分: 1.语法格式 2.线程调度情况 3.编程注意事项 4.练一练 * 阅读提示 :鼠标悬停在 章节标题 上可见 文章目录 异步编程(Task Asynchronous Progra ...

  8. Vue2/Vue3 项目生产环境开启 vue devtools 插件线上调试 vue 组件

    说到 vue 项目的调试工具,必然少不了 "vue devtools 插件",此插件就像"手术刀"一样,是开发环境下的一个利器,生产环境一般情况没办法使用. 要 ...

  9. es6 export和export default的区别

    相同点 export 与 export default 均可用于导出常量.函数.文件.模块 可在其它文件或模块中通过import+(常量 | 函数 | 文件 | 模块)名的方式,将其导入,以便能够对其 ...

  10. codelite常用快捷键积累

    博客地址:https://www.cnblogs.com/zylyehuo/ 编译整个工作空间 workplace Ctrl+shift+B 编译当前文件 file Ctrl+F7 编译项目 proj ...