Description

  有一个长度为n的数组{a1,a2,...,an}。m次询问,每次询问一个区间内最小没有出现过的自然数。

Input

  第一行n,m。
  第二行为n个数。
  从第三行开始,每行一个询问l,r。

Output

  一行一个数,表示每个询问的答案。

Sample Input

5 5
2 1 0 2 1
3 3
2 3
2 4
1 2
3 5

Sample Output

1
2
3
0
3

HINT

数据规模和约定

  对于100%的数据:

  1<=n,m<=200000

  0<=ai<=109

  1<=l<=r<=n

  对于30%的数据:

  1<=n,m<=1000

Source

题目大意

  区间询问mex。

Solution 1 Mo's Algorithm & Block Division

  区间求mex?不会,直接莫队。

  由于一个数大于等于$n$时无意义,所以按$n$分块,每块记录是否完全被覆盖。

  查询时暴力跳。

  表示数据真水,最开始某个地方的$x$,写成$p$竟然A了。

Code

 /**
* bzoj
* Problem#3585
* Accepted
* Time: 6832ms
* Memory: 5988k
*/
#include <bits/stdc++.h>
using namespace std;
typedef bool boolean; const int cs = ; typedef class Query {
public:
int l, r;
int id; Query() { } boolean operator < (Query b) const {
if (l / cs != b.l / cs) return l < b.l;
return r < b.r;
}
}Query; int n, m;
int* ar;
Query* qs;
int exist[];
int cover[cs];
int *res; inline void init() {
scanf("%d%d", &n, &m);
ar = new int[(n + )];
qs = new Query[(m + )];
res = new int[(m + )];
for (int i = ; i <= n; i++)
scanf("%d", ar + i);
for (int i = ; i <= m; i++)
scanf("%d%d", &qs[i].l, &qs[i].r), qs[i].id = i;
} inline void update(int p, int sign) {
int x = ar[p];
if (x >= n) return;
if (!exist[x] && sign == ) cover[x / cs]++;
exist[x] += sign;
if (!exist[x] && sign == -)cover[x / cs]--;
} inline void solve() {
sort(qs + , qs + m + );
int mdzzl = , mdzzr = ;
for (int i = ; i <= m; i++) {
while (mdzzr < qs[i].r) update(++mdzzr, );
while (mdzzr > qs[i].r) update(mdzzr--, -);
while (mdzzl < qs[i].l) update(mdzzl++, -);
while (mdzzl > qs[i].l) update(--mdzzl, ); for (int j = ; j < cs; j++) {
if (cover[j] < cs) {
int k = j * cs;
while (exist[k]) k++;
res[qs[i].id] = k;
break;
}
}
} for (int i = ; i <= m; i++)
printf("%d\n", res[i]);
} int main() {
init();
solve();
return ;
}

分块&莫队

Solution 2 Segment Tree

  假设你通过某种方式求出了$[1, i]$的答案。

  考虑删掉位置1,那么位置上的数到下一次它出现之前都可以用来更新答案。

  于是线段树区间修改,单点查询,做完了。

Code

 /**
* bzoj
* Problem#3585
* Accepted
* Time: 4436ms
* Memory: 15184k
*/
#include <bits/stdc++.h>
using namespace std;
typedef bool boolean; #define smin(_a, _b) (_a > _b) ? (_a = _b) : (0) typedef class Query {
public:
int l, r, id, next;
}Query; typedef class SegTreeNode {
public:
int val;
SegTreeNode *l, *r; SegTreeNode():l(NULL), r(NULL) { }
}SegTreeNode; SegTreeNode pool[];
SegTreeNode* top = pool; SegTreeNode* newnode(int val) {
top->val = val;
return top++;
} typedef class SegTree {
public:
SegTreeNode* rt; SegTree() { }
SegTree(int n, int* f) {
build(rt, , n, f);
} void build(SegTreeNode*& p, int l, int r, int* f) {
p = newnode();
if (l == r) {
p->val = f[l];
return;
}
int mid = (l + r) >> ;
build(p->l, l, mid, f);
build(p->r, mid + , r, f);
} void update(SegTreeNode* p, int l, int r, int ql, int qr, int val) {
if (l == ql && r == qr) {
smin(p->val, val);
return;
}
int mid = (l + r) >> ;
if (qr <= mid)
update(p->l, l, mid, ql, qr, val);
else if (ql > mid)
update(p->r, mid + , r, ql, qr, val);
else {
update(p->l, l, mid, ql, mid, val);
update(p->r, mid + , r, mid + , qr, val);
}
} int query(SegTreeNode* p, int l, int r, int idx) {
if (l == idx && r == idx)
return p->val;
int mid = (l + r) >> , rt = p->val, a = ;
if (idx <= mid)
a = query(p->l, l, mid, idx);
else
a = query(p->r, mid + , r, idx);
return (a < rt) ? (a) : (rt);
}
}SegTree; int n, m;
int *ar, *suf;
int *last, *res;
Query *qs;
int *h, *f;
SegTree st;
boolean *exist; inline void init() {
scanf("%d%d", &n, &m);
h = new int[(n + )];
f = new int[(n + )];
ar = new int[(n + )];
suf = new int[(n + )];
res = new int[(m + )];
qs = new Query[(m + )];
last = new int[(n + )];
exist = new boolean[(n + )];
fill(h, h + n + , );
fill(suf, suf + n + , n + );
fill(last, last + n + , );
fill(exist, exist + n + , false);
for (int i = , x; i <= n; i++) {
scanf("%d", ar + i);
if (ar[i] >= n) continue;
x = ar[i];
if (last[x])
suf[last[x]] = i;
last[x] = i;
}
for (int i = ; i <= m; i++) {
scanf("%d%d", &qs[i].l, &qs[i].r);
qs[i].id = i, qs[i].next = h[qs[i].l], h[qs[i].l] = i;
}
} inline void prepare() {
int p = ;
for (int i = ; i <= n; i++) {
if (ar[i] < n)
exist[ar[i]] = true;
while (exist[p]) p++;
f[i] = p;
}
st = SegTree(n, f);
} inline void solve() {
for (int i = ; i <= n; i++) {
for (int j = h[i]; j; j = qs[j].next)
res[qs[j].id] = st.query(st.rt, , n, qs[j].r);
if (ar[i] < n) {
st.update(st.rt, , n, i, suf[i] - , ar[i]);
}
}
for (int i = ; i <= m; i++)
printf("%d\n", res[i]);
} int main() {
init();
prepare();
solve();
return ;
}

bzoj 3585 mex - 线段树 - 分块 - 莫队算法的更多相关文章

  1. BZOJ.3585.mex(线段树)

    题目链接 题意:多次求区间\(mex\). 考虑\([1,i]\)的\(mex[i]\),显然是单调的 而对于\([l,r]\)与\([l+1,r]\),如果\(nxt[a[l]]>r\),那么 ...

  2. BZOJ 1878 [SDOI2009]HH的项链 (主席树 或 莫队算法)

    题目链接  HH的项链 这道题可以直接上主席树的模板 #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) ...

  3. 【BZOJ-3809】Gty的二逼妹子序列 分块 + 莫队算法

    3809: Gty的二逼妹子序列 Time Limit: 80 Sec  Memory Limit: 28 MBSubmit: 1072  Solved: 292[Submit][Status][Di ...

  4. bzoj 2038 A-小Z的袜子[hose] - 莫队算法

    作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 具体来说,小Z把这N只袜子从1到N编号,然后从 ...

  5. bzoj 3289 Mato的文件管理(莫队算法+BIT)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3289 [题意] 回答若干个询问:[l,r]区间内的逆序对个数. [思路] 莫队算法,B ...

  6. bzoj 2308 小Z的袜子(莫队算法)

    小Z的袜子 [题目链接]小Z的袜子 [题目类型]莫队算法 &题解: 莫队算法第一题吧,建议先看这个理解算法,之后在参考这个就可以写出简洁的代码 我的比第2个少了一次sort,他的跑了1600m ...

  7. bzoj 2038 小Z的袜子 莫队算法

    题意 给你一个长度序列,有多组询问,每次询问(l,r)任选两个数相同的概率.n <= 50000,数小于等于n. 莫队算法裸题. 莫队算法:将序列分为根号n段,将询问排序,以L所在的块为第一关键 ...

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

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

  9. BZOJ 3585: mex [主席树]

    3585: mex Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 787  Solved: 422[Submit][Status][Discuss] ...

随机推荐

  1. 查看Linux内核版本

    您可能因多种原因需要确切知道GNU / Linux操作系统上运行的内核版本. 也许您正在调试与硬件相关的问题,或者了解影响旧内核版本的新安全漏洞,并且您想知道您的内核是否易受攻击. 无论是什么原因,从 ...

  2. 世界上最大的软件注册表-----npm

    npm 是什么? npm 为你和你的团队打开了连接整个 JavaScript 天才世界的一扇大门.它是世界上最大的软件注册表,每星期大约有 30 亿次的下载量,包含超过 600000 个 包(pack ...

  3. 2 Android程序的执行

    Android系统采用的是分层架构,分四层: 1.  Applicitations:应用层 2.  Applicitation Framework:架构层 3.  Libraries:类库层 4.  ...

  4. 记Html的初次接触

    第一次接触Html是在昨天的培训班体验课上,这一次课我明白了许多. 1.程序语言比我想象中还要多(原来除了C与Java还有这么多) 2.程序员毕业后掌握7种语言是很正常的事(难怪程序员会秃顶) 3.H ...

  5. Kafka Streams开发入门(2)

    背景 上一篇我们介绍了Kafka Streams中的消息转换操作map,今天我们给出另一个经典的转换操作filter的用法.依然是结合一个具体的实例展开介绍. 演示功能说明 本篇演示filter用法, ...

  6. java版ftp简易客户端(可以获取文件的名称及文件大小)

    java版ftp简易客户端(可以获取文件的名称及文件大小) package com.ccb.ftp; import java.io.IOException; import java.net.Socke ...

  7. InvalidOperationException: No file provider has been configured to process the supplied file.

    现在有一个api, 提供图片的下载,如下代码,,调试出现 InvalidOperationException: No file provider has been configured to proc ...

  8. jq 实现切换菜单选中状态

    点击导航菜单,切换选中状态 效果: 思路:首先获取选中的URL,再通过正则判断是否相同,相同就加上相应的属性,不相同就去除相应的属性. html代码 <div class="layui ...

  9. python 读写excel(xls格式)

    import xlrd #导入模块 from xlutils.copy import copy #导入copy模块 rb = xlrd.open_workbook(r"e:\额度导入表.xl ...

  10. Centos7下的日志切割--转发

    logrotate /etc/logrotate.conf 是 Logrotate 工具的一个配置文件,这个工具用来自动切割系统日志,Logrotate 是基于 cron 来运行的,如下: [root ...