链接

https://www.luogu.org/problemnew/show/P4137

思路

做了好几次,每次都得想一会,再记录一下

可持久化权值线段树

区间出现存最小的下标

然后线段树上二分

如果左边min>L

那就去右边

因为左边都被【L,R】占满了

虽然比卡常的莫队慢好多(700ms和1000ms)

但是理论上快哇

线段树

// luogu-judger-enable-o2
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 7;
const int inf = 0x3f3f3f3f;
inline int read() {
int x = 0, f = 1; char s = getchar();
for(; s > '9' || s < '0'; s = getchar()) if(s == '-') f = -1;
for(; s >= '0' && s <= '9'; s = getchar()) x = x * 10 + s - '0';
return x * f;
}
int n, m, a[N], rt[N];
namespace seg_tree {
#define ls e[rt].ch[0]
#define rs e[rt].ch[1]
struct node {int ch[2],mex;}e[N*31];
int cnt;
void modify(int &rt, int old, int l, int r, int L) {
rt = ++cnt;
e[rt] = e[old];
if(l == r) {
e[rt].mex = L;
return;
}
int mid = (l + r) >> 1;
if(a[L] <= mid) modify(ls, e[old].ch[0], l, mid, L);
else modify(rs, e[old].ch[1], mid + 1, r, L);
e[rt].mex = min(e[ls].mex ,e[rs].mex);
}
int query(int rt, int l, int r, int L) {
if(l == r) return l;
int mid = (l + r) >> 1;
if(e[ls].mex >= L) return query(rs, mid + 1, r, L);
else return query(ls, l, mid, L);
}
}
int main() {
n = read(), m = read();
for (int i = 1; i <= n; ++i) a[i] = min(read(), 200000);
for (int i = 1; i <= n; ++i) {
seg_tree::modify(rt[i], rt[i-1], 0, 200000, i);
}
for (int i = 1; i <= m; ++i) {
int x = read(), y = read();
printf("%d\n", seg_tree::query(rt[y], 0, 200000, x));
}
return 0;
}

莫队

// luogu-judger-enable-o2
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdio>
#define maxn 301001
using namespace std;
int n,m,now;
int a[maxn];
int belong[maxn];
int vis[maxn];
int ma;
struct node {
int l,r,id;
} q[maxn];
int ans[maxn];
inline int read() {
int x=0,f=1;char s=getchar();
while('0'>s||s>'9') {if(s=='-') f=-1;s=getchar();}
while('0'<=s&&s<='9') {x=x*10+s-'0';s=getchar();}
return x*f;
}
inline bool cmp(node a,node b) {
return belong[a.l]==belong[b.l] ? belong[a.l]&1 ? a.r<b.r : a.r>b.r : belong[a.l]<belong[b.l];
}
inline void add(int x) {
++vis[x];
if(now < x) return;
if(now==x&&vis[x]==1) {
for(int i=now+1; i<n; ++i) {
if(!vis[i]) {
now=i;
return;
}
}
}
}
inline void delet(int x) {
--vis[x];
if(now < x) return;
if(now > x) {
if(!vis[x]) {
now=x;
}
}
}
int main() { n=read();
m=read();
int k=n/sqrt(m);
for(int i=1; i<=n; ++i) {
a[i]=read();
if(a[i] > n)
a[i]=n+1;
}
for(int i=1; i<=n; ++i)
belong[i]=(i-1)/k+1;
for(int i=1; i<=m; ++i)
{
q[i].l=read();
q[i].r=read();
q[i].id=i;
}
sort(q+1,q+1+m,cmp);
int l=1,r=0;
for(int i=1; i<=m; ++i) {
while(l > q[i].l) add(a[--l]);
while(l < q[i].l) delet(a[l++]);
while(r < q[i].r) add(a[++r]);
while(r > q[i].r) delet(a[r--]);
ans[q[i].id]=now;
}
for(int i=1; i<=m; ++i)
printf("%d\n",ans[i]);
return 0;
}

P4137 Rmq Problem / mex的更多相关文章

  1. P4137 Rmq Problem / mex (莫队)

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

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

    P4137 Rmq Problem /mex 题意 给一个长为\(n(\le 10^5)\)的数列\(\{a\}\),有\(m(\le 10^5)\)个询问,每次询问区间的\(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

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

  5. Luogu P4137 Rmq Problem / mex

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

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

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

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

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

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

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

  9. luogu P4137 Rmq Problem / mex(可持久化线段树)

    一开始想的是莫队,然后维护几个bitset,然后瞎搞.脑子里想了想实现,发现并不好写. 还是主席树好写.我们维护一个权值的线段树,记录每一个权值的最后一次出现的位置下标.我们查询的时候要在前\(r\) ...

随机推荐

  1. Redis实现分布式Session

    相关博客: http://www.cnblogs.com/yanweidie/p/4763556.html http://www.cnblogs.com/lori/p/5368722.html?utm ...

  2. ResourceExhaustedError 解决方案

    原因:网络层太多,运算量太大导致GPU资源耗尽 解决方案: 1.限制GPU的使用: config = tf.ConfigProto()config.gpu_options.per_process_gp ...

  3. Yii Restful api自定义字段

  4. 多线程(threading)示例

    一.多线程简单示例 import threading,time print('第一线程(默认):程序开始啦!') def takeANap(): time.sleep(5) print('第二线程:5 ...

  5. python内置函数zip

    zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表. 如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以 ...

  6. mac电脑使用,开发环境配置指南

    mac电脑使用,开发环境配置指南 前端工具链,mac下都很好用 用brew来装软件 用brew cask来装应用 Introduction · macOS Setup Guidehttp://sour ...

  7. html 基本布局介绍

    1.div默认是纵向排列的,例子如下: <div id="wrap"> <div id="div1">div1</div> ...

  8. ajax 检测用户名是否可用

    下面是一个 ajax 检测用户名是否可用的例子. django  项目中. —— views.py 里—— from django.shortcuts import render,HttpRespon ...

  9. mysql命令(三)

    创建一个名字为Student库: create database Student; 用以下地命令来查看创建的数据库是否成功: show databases; 进入数据库: use Student; 用 ...

  10. node.js的on、emit、off封装

    //绑定事件.触发事件和移除事件 //绑定事件 //on(eventName,cb){} //第一步判断当前事件是否存在,如果不存在则初始化:key:[],然后在将回调函数添加到数据中去 let ev ...