链接

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. 【AngularJS】解决ng-if中的ng-model值无效的问题(转)

    from:http://blog.csdn.net/u013451157/article/details/60866210 与其他指令一样,ng-if指令也会创建一个子级作用域,因此,如果在ng-if ...

  2. orm查询语法参考文章

    1.参考博客 http://blog.csdn.net/OyangYujun/article/details/45938905 ORMLite完全解析(三)官方文档第三章.自定义查询构造器 Custo ...

  3. Usefull Resources

    Sql Server Profiler 1. http://www.cnblogs.com/Fooo/archive/2013/02/19/2916789.html 2. http://5439255 ...

  4. SQL query - check latest 3 days failed job.

    select top 100 js.last_run_date ,j.name, js.step_id,js.step_name,js.last_run_date,jsl.log,jh.message ...

  5. GO富集分析

    GO的主要用途之一是对基因组进行富集分析.例如,给定一组在特定条件下上调的基因,富集分析将使用该基因组的注释发现哪些GO术语被过度表示(或未充分表示). 富集分析工具    用户可以直接从GOC网站的 ...

  6. xml 的 <![CDATA["URL"]]>

    <![CDATA["URL"]]>:用于 xml 处理特殊字符,比如:& <PolicyURL><![CDATA[ http://ectp.t ...

  7. 给定一个正整数,实现一个方法求出离该整数最近的大于自身的 换位数 <把一个整数各个数位进行全排列>

    """给定一个正整数,实现一个方法求出离该整数最近的大于自身的 换位数 -> 把一个整数各个数位进行全排列""" # 使用 permu ...

  8. C# 设置按钮快捷键

    参考自:http://www.csharpwin.com/csharpspace/3932r8132.shtml 一.C# button快捷键之第一种:Alt + *(按钮快捷键) 在Button按钮 ...

  9. linux /etc/shadow--passwd/pam.d/system-auth文件详解

     在linux操作系统中, /etc/passwd文件中的每个用户都有一个对应的记录行,记录着这个用户的一下基本属性.该文件对所有用户可读.   而/etc/shadow文件正如他的名字一样,他是pa ...

  10. Android屏幕适配全攻略(最权威的官方适配指导)

    摘自:http://www.cocoachina.com/android/20151030/13971.html Android屏幕适配出现的原因 在我们学习如何进行屏幕适配之前,我们需要先了解下为什 ...