bzoj 3585 mex - 线段树 - 分块 - 莫队算法
Description
有一个长度为n的数组{a1,a2,...,an}。m次询问,每次询问一个区间内最小没有出现过的自然数。
Input
第一行n,m。
第二行为n个数。
从第三行开始,每行一个询问l,r。
Output
一行一个数,表示每个询问的答案。
Sample Input
2 1 0 2 1
3 3
2 3
2 4
1 2
3 5
Sample Output
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 - 线段树 - 分块 - 莫队算法的更多相关文章
- BZOJ.3585.mex(线段树)
题目链接 题意:多次求区间\(mex\). 考虑\([1,i]\)的\(mex[i]\),显然是单调的 而对于\([l,r]\)与\([l+1,r]\),如果\(nxt[a[l]]>r\),那么 ...
- BZOJ 1878 [SDOI2009]HH的项链 (主席树 或 莫队算法)
题目链接 HH的项链 这道题可以直接上主席树的模板 #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) ...
- 【BZOJ-3809】Gty的二逼妹子序列 分块 + 莫队算法
3809: Gty的二逼妹子序列 Time Limit: 80 Sec Memory Limit: 28 MBSubmit: 1072 Solved: 292[Submit][Status][Di ...
- bzoj 2038 A-小Z的袜子[hose] - 莫队算法
作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 具体来说,小Z把这N只袜子从1到N编号,然后从 ...
- bzoj 3289 Mato的文件管理(莫队算法+BIT)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3289 [题意] 回答若干个询问:[l,r]区间内的逆序对个数. [思路] 莫队算法,B ...
- bzoj 2308 小Z的袜子(莫队算法)
小Z的袜子 [题目链接]小Z的袜子 [题目类型]莫队算法 &题解: 莫队算法第一题吧,建议先看这个理解算法,之后在参考这个就可以写出简洁的代码 我的比第2个少了一次sort,他的跑了1600m ...
- bzoj 2038 小Z的袜子 莫队算法
题意 给你一个长度序列,有多组询问,每次询问(l,r)任选两个数相同的概率.n <= 50000,数小于等于n. 莫队算法裸题. 莫队算法:将序列分为根号n段,将询问排序,以L所在的块为第一关键 ...
- 主席树||可持久化线段树+离散化 || 莫队+分块 ||BZOJ 3585: mex || Luogu P4137 Rmq Problem / mex
题面:Rmq Problem / mex 题解: 先离散化,然后插一堆空白,大体就是如果(对于以a.data<b.data排序后的A)A[i-1].data+1!=A[i].data,则插一个空 ...
- BZOJ 3585: mex [主席树]
3585: mex Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 787 Solved: 422[Submit][Status][Discuss] ...
随机推荐
- CMU-Multimodal SDK Version 1.1 (mmsdk)使用方法总结
年10月26日 星期六 mmdatasdk: module for downloading and procesing multimodal datasets using computational ...
- drf--视图家族
目录 drf 视图家族 前期准备 总路由 urls.py 基表:utils/models.py 模型层 api/models.py 序列化器 api/serializers.py 基本视图(views ...
- Linux配置swap
根据自己的物理内存分配合适的swap大小 下面是合适的配置 物理内存 交换分区(swap) <=4G 至少2G 4-16G 至少4G 16G-64 至少8G 下面是操作步骤 1.首先查看我们的内 ...
- 关于mysql数据库涉及的一些规范
tips:如果本文对你有用,请爱心点个赞,提高排名,让这篇文章帮助更多的人.谢谢大家!比心❤~ 如果解决不了,可以在文末加我微信,进群交流. 设计规范,在分工协作的工作场景中尤其重要,否则团队之间互相 ...
- Linux下 svn相关操作
Linux下 svn相关操作 一.首先看看svn安装的位置: 命令: find / -name svn /var/svn :表示安装目录 /user/bin/svn :表示命令目录 可以看到的是svn ...
- Mac安装vscode IDE 撸nodejs代码
1. vscode官网地址:https://code.visualstudio.com 找到mac对应的下载地址,下载后的文件是 zip压缩包,解压后将文件拖到Application目录下即可. ...
- ElasticSearch(十三):Spring Data ElasticSearch 的使用(三)——NativeSearchQuery 高亮查询
在Elasticsearch的实际应用中,经常需要将匹配到的结果字符进行高亮显示,此处采取NativeSearchQuery原生查询的方法,实现查询结果的高亮显示. /** * 高亮查询 */ @Te ...
- 如何预防SQL注入
归纳一下,主要有以下几点: 1.永远不要信任用户的输入.对用户的输入进行校验,可以通过正则表达式,或限制长度:对单引号和 双"-"进行转换等. 2.永远不要使用动态拼装sql,可以 ...
- web服务器-nginx
一.nginx之前 同步与异步: 同步与异步的重点在消息通知的方式上,也就是调用结果的通知方式不同. 同步:当一个同步调用发出去后,调用者要一直等待调用的结果通知后,才能进行后续的操作. 异步:当一个 ...
- 上传自己的构件(Jar)到Maven中央仓库
背景: 用了Maven之后,你有没有这样的想法,自己一直在使用别人贡献的代码,自己能不能把自己觉得好的代码也贡献出来让大家方便. 还有如果你也是一名程序员,你会不会觉得要是把自己积累起来日常常用的代码 ...