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] ...
随机推荐
- 不用Pageant告别Pageant Windows10下TortoiseGit和Git配置使用同一SSH密钥
关于Git使用SSH免密连接参考:https://blog.csdn.net/qq_32786873/article/details/80570788 关于Windows10下TortoiseGit使 ...
- Elasticsearch DSL 常用语法介绍
课程环境 CentOS 7.3 x64 JDK 版本:1.8(最低要求),主推:JDK 1.8.0_121 Elasticsearch 版本:5.2.0 相关软件包百度云下载地址(密码:0yzd):h ...
- jackson 学习资料
源代码托管地址 https://github.com/FasterXML/jackson https://github.com/FasterXML/jackson-docs http://www.st ...
- 《微信小程序项目开发实战:用WePY、mpvue、Taro打造高效的小程序》(笔记1)WePY开发环境的安装
WePY的安装或更新都通过npm进行,全局安装或更新WePY命令行工具,使用以下命令: npm install wepy-cli -g 稍等片刻,成功安装后,即可创建WePY项目. 注意:如果npm安 ...
- Python 的稀疏矩阵
什么是稀疏矩阵 简单的说,如果一个矩阵中大部分元素为0,就被称为稀疏矩阵. 对于稀疏矩阵而言,实际存储的数据项很少.如果在计算机中采用传统的二维数组(Python中用二维列表)来存储稀疏矩阵,就会浪费 ...
- Java梗概
Java平台:J2SE(桌面).J2ME(逐渐被android取代).J2EE(企业级针对web程序) Java是在JVM虚拟机上运行,跨平台本质是在不同平台上运行JVM虚拟机 JRE = JVM+核 ...
- pycharm 里运行 django 工程 You must either define the environment variable DJANGO_SETTINGS_MODULE 错误
pycharm 里运行 django 工程出现错误(在命令行直接运行ok): django.core.exceptions.ImproperlyConfigured: Requested settin ...
- org.apache.catalina.core.StandardService - Stopping service [Tomcat]
今天在启动springboot项目突然启动失败,但是在测试日志文件,以为是日志出错,下面这个是logback打印的异常信息. 2019-05-30 15:09:10.686 [restartedMai ...
- Prometheus学习笔记(4)什么是pushgateway???
目录 一.pushgateway介绍 二.pushgateway的安装运行和配置 三.自定义脚本发送pushgateway 四.使用pushgateway的优缺点 一.pushgateway介绍 pu ...
- 提高用git下载代码时的成功率
在用git clone下载一些比较大的仓库时,经常会遇到由于仓库体积过大,网络也不稳定,导致下了半截就中断了,可以参考如下的下载方法. 先用创建一个空目录,然后用git init初始化,然后用git ...