Mex

问题提出

有一个长度为nnn的数组{a1,a2,…,an}\{a_1,a_2,…,a_n\}{a1​,a2​,…,an​}。mmm次询问,每次询问一个区间内最小没有出现过的自然数。

题目解答

对1−n1-n1−n这里能够的每个数xxx,都统计出来在数组中出现的位置,并在前补上000,在后补上n+1n+1n+1.

例如数组{1,2,3,2,1}\{1,2,3,2,1\}{1,2,3,2,1},
其中111出现过的位置就是:{0,1,5,6}\{0,1,5,6\}{0,1,5,6}
其中222出现过的位置就是:{0,2,4,6}\{0,2,4,6\}{0,2,4,6}
其中333出现过的位置就是:{0,3,6}\{0,3,6\}{0,3,6}
其中444出现过的位置就是:{0,6}\{0,6\}{0,6}
其中555出现过的位置就是:{0,6}\{0,6\}{0,6}

如果一个自然数xxx没有在一个区间[l,r][l,r][l,r]中出现过,那么必然存在xxx的出现序列中的两个位置p1,p2p_1,p_2p1​,p2​满足p1&lt;l&lt;r&lt;p2p_1&lt;l&lt;r&lt;p_2p1​<l<r<p2​.

那么这就变成一个经典的222维数点问题啦!

我们把每个xxx的出现位置序列,相邻两个数并成一个二维数点,插入到线段树中去.

对于每个询问(l,r)(l,r)(l,r)在线段树中找满足p1&lt;l&lt;r&lt;p2p_1&lt;l&lt;r&lt;p_2p1​<l<r<p2​条件的权值最小的点就可以了.

将所有的询问(l,r)(l,r)(l,r)和数点p1,p2p_1,p_2p1​,p2​按照第二维排序,从左往右枚举,遇到询问就回答,遇到数点就插入.

排序可以省掉一维.

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>
#define pr(x) std::cout << #x << ':' << x << std::endl
#define rep(i,a,b) for(int i = a;i <= b;++i)
#define repi(i,a,b) for(int i = a;i >= b;--i)
#define clr(x) memset(x,0,sizeof(x))
#define setinf(x) memset(x,0x3f,sizeof(x))const int N = 200010;
const int inf = 1e9+7;
int n,m;
int a[N];
std::map<int,int> map;struct node{int num;node(int x = inf){num = x;}
}ns[N<<2];struct que{int l,r,id;que(int l = 0,int r = 0,int id = 0) {this->l = l,this->r = r,this->id = id;}bool operator<(const que &q)const{return l < q.l;}
}qs[N],qs2[N<<2];int ans[N];node maintain(node &lch,node &rch) {node res = node();res.num = std::min(lch.num,rch.num);return res;
}   void change(int o,int l,int r,int pos,int val) {if(l == r) {if(val < ns[o].num) ns[o].num = val;return ;}int mid = (l + r) >> 1;if(pos <= mid) change(o<<1,l,mid,pos,val);else change(o<<1|1,mid+1,r,pos,val);ns[o] = maintain(ns[o<<1],ns[o<<1|1]);
}node query(int o,int l,int r,int ql,int qr) {if(ql <= l && r <= qr) return ns[o];if(r < ql || qr < l)return node();  int mid = (l + r) >> 1;node lch = query(o<<1,l,mid,ql,qr);node rch = query(o<<1|1,mid+1,r,ql,qr);return maintain(lch,rch);
}void build(int o,int l,int r) {if(l == r) {ns[o] = node();return ;}int mid = (l + r) >> 1;build(o<<1,l,mid);build(o<<1|1,mid+1,r);ns[o] = maintain(ns[o<<1],ns[o<<1|1]);
}int main() {std::ios::sync_with_stdio(false);std::cin >> n >> m;build(1,0,n+1);rep(i,1,n) std::cin >> a[i];int cc = 0;rep(i,1,n){qs2[cc++] = que(map[a[i]],i,a[i]);map[a[i]] = i;}rep(i,0,2*n) {qs2[cc++] = que(map[i],n+1,i);}std::sort(qs2,qs2+cc);rep(i,1,m) {std::cin >> qs[i].l >> qs[i].r;qs[i].id = i;}   std::sort(qs+1,qs+1+m);int pos = 0;rep(i,1,m) {while(pos < cc && qs2[pos].l < qs[i].l){change(1,0,n+1,qs2[pos].r,qs2[pos].id);++pos;}node res = query(1,0,n+1,qs[i].r+1,n+1);ans[qs[i].id] = res.num;}rep(i,1,m) {std::cout << ans[i] << std::endl;}}

线段树-Mex-洛谷P4137相关推荐

  1. 线段树——最大数——洛谷——1198

    这题可以说是模板题了. 只需要预先开好m大小的线段树,就好了,这就可以处理加点的问题. #include<iostream> #include<cstdio> #include ...

  2. (线段树)洛谷 P2471 [SCOI2007]降雨量

    原题地址 https://www.luogu.com.cn/problem/P2471 解题思路 准备 好像只有我维护了两棵线段树? 先定义一个 rain\textit{rain}rain 数组存放降 ...

  3. 【模板】线段树 2 洛谷P3373

    题目描述 如题,已知一个数列,你需要进行下面三种操作: 将某区间每一个数乘上 xx 将某区间每一个数加上 xx 求出某区间每一个数的和 输入格式 第一行包含三个整数 n,m,pn,m,p,分别表示该数 ...

  4. 字典树模板+洛谷P2580 于是他错误的点名开始了

    题目: 题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 他会一边搓炉石一边点名以至于有一天他连续点到了某个同学两次,然后正好被路过的校长发现了然后就是一顿欧拉欧拉欧拉(详情请见已结束比赛 CON ...

  5. 线段覆盖(洛谷P1803题题解,C++语言描述)

    题目要求 P1803题目链接 分析 这题是一个线段覆盖问题,但并不是很复杂,也是贪心思想. 想要尽可能放线段,不能重合(可以正好相交),那就可以每一次只关注右端点,尽可能地选择剩余未选的线段中右端点最 ...

  6. 支配树(洛谷-P5180)

    题目描述 给定一张有向图,求从1号点出发,每个点能支配的点的个数(包括自己) 输入输出格式 输入格式: 第一行两个正整数n,mn,m,表示点数和边数 接下来mm行,每行输入两个整数u,vu,v,表示有 ...

  7. 校门外的树(洛谷-P1047)

    题目描述 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0,1,2,--,L,都种 ...

  8. Trie树【洛谷P3879】 [TJOI2010]阅读理解

    P3879 [TJOI2010]阅读理解 题目描述 英语老师留了N篇阅读理解作业,但是每篇英文短文都有很多生词需要查字典,为了节约时间,现在要做个统计,算一算某些生词都在哪几篇短文中出现过. 输入输出 ...

  9. 洛谷(P3373)线段树加乘混合模板

    题目链接:P3373 [模板]线段树 2 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 这道题目的意思很明确,就是要我们在线完成区间的乘和加运算并支持查询区间和的一个问题.处理这道 ...

  10. 20.CF817F MEX Queries 线段树(Lazy标记练习)

    20.CF817F MEX Queries 离散化+区间覆盖+区间反转线段树 个人Limitの线段树题单题解主目录:Limitの线段树题单 题解目录_HeartFireY的博客-CSDN博客 要求维护 ...

最新文章

  1. java自增运算符与自减运算符
  2. WPF:数据绑定--PropertyChangeNotification属性更改通知
  3. solr4.6本地数据提交异常
  4. 设计模式(九)——适配器模式
  5. 深度学习- 激活函数总结(Sigmoid, Tanh, Relu, leaky Relu, PReLU, Maxout, ELU, Softmax,交叉熵函数)
  6. mini车f和r的区别_最大最实用的MINI,最值得买的MINI?
  7. MySql表大小、行大小和列大小的限制
  8. utilities——C++常用仿函数
  9. 情人节,教你用Python定时给小姐姐微信发送专属问候!
  10. Hbase 权威指南
  11. 课设 stm32的8路电压表采集系统
  12. win10修改计算机物理地址,两种方法教您修改Win10 Professional MAC物理地址
  13. 六安一中2021高考成绩查询,六安一中
  14. YOLOv1的pytorch复现版本,博主亲自测试完整复现。
  15. tomcat配置桌面快捷启动文件
  16. dom4j解析xml报错
  17. [windows]win10家庭版切换到管理员账户
  18. 基于关联规则的足球比赛数据分析
  19. [渝粤教育] 中国地质大学 城镇规划 复习题 (2)
  20. 令人拍案叫绝的 Wasserstein GAN,彻底解决GAN训练不稳定问题

热门文章

  1. mysql group where_[MySQL] 测试where group by order by的索引问题
  2. python面向对象编程思想书籍_Python的面向对象编程思想
  3. leetcode-349-两个数组的交集
  4. C++中输入一组数字 以换行符结束输入
  5. mysql下载了解压版怎么_教你安装Mysql(解压版/非安装包)图文教程
  6. [SpringBoot2]定制化原理_SpringBoot定制化组件的几种方式
  7. 布斯乘法以及带符号数的运算
  8. [C++STL]map容器用法介绍
  9. LeetCode 501二叉搜索树中的众数-简单
  10. 八数码问题II-双向bfs和map标记