[BZOJ 3585] mex 【莫队+分块】
题目链接:BZOJ - 3585
题目分析
区间mex,即区间中没有出现的最小自然数。
那么我们使用一种莫队+分块的做法,使用莫队维护当前区间的每个数字的出现次数。
然后求mex用分块,将权值分块(显然mex 一定小于等于 n ,大于 n 的权值没有意义,可以直接忽略),每块大小 sqrt(n) 。
然后区间中的某个数的数量被减到0的时候就将它所在的块的种类计数减一,添加数的时候类似。
然后枚举每个块,找到最小的中间有数不存在的块(即种类数小于块中的数的种数),然后到这个快里直接从小一个一个找到第一个不存在的数。
这样莫队的复杂度和分块的复杂度是相加的, O(n^1.5) + O(n^1.5) = O(n^1.5) 。
代码
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm> using namespace std; const int MaxN = 200000 + 5, MaxQ = 200000 + 5, MaxB = 500 + 5; int n, m, BlkSize, MaxBlk;
int A[MaxN], Blk[MaxN], L[MaxB], R[MaxB], Ans[MaxQ], Cnt[MaxN], V[MaxB], Size[MaxB]; struct Query
{
int Idx, l, r, v;
} Q[MaxQ]; inline bool Cmp(Query q1, Query q2)
{
if (q1.v == q2.v) return q1.r < q2.r;
return q1.v < q2.v;
} inline void Del_Num(int x)
{
--Cnt[x];
if (Cnt[x] == 0) --V[Blk[x]];
} inline void Add_Num(int x)
{
if (Cnt[x] == 0) ++V[Blk[x]];
++Cnt[x];
} void Pull(int f, int x, int y)
{
if (x == y) return;
if (f == 0)
{
if (x < y)
{
for (int i = x; i < y; ++i)
Del_Num(A[i]);
}
else
{
for (int i = x - 1; i >= y; --i)
Add_Num(A[i]);
}
}
else
{
if (x < y)
{
for (int i = x + 1; i <= y; ++i)
Add_Num(A[i]);
}
else
{
for (int i = x; i > y; --i)
Del_Num(A[i]);
}
}
} int Get_Ans()
{
int ret = n;
for (int i = 1; i <= MaxBlk; ++i)
if (V[i] < Size[i])
{
for (int j = L[i]; j <= R[i]; ++j)
if (Cnt[j] == 0)
{
ret = j;
break;
}
break;
}
return ret;
} int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i)
{
scanf("%d", &A[i]);
if (A[i] > n) A[i] = n + 1;
}
BlkSize = (int)sqrt((double)n);
for (int i = 0; i <= n; ++i) Blk[i] = i / BlkSize + 1;
MaxBlk = Blk[n];
for (int i = 1; i <= MaxBlk; ++i)
{
L[i] = (i - 1) * BlkSize;
R[i] = i * BlkSize - 1;
Size[i] = R[i] - L[i] + 1;
}
R[MaxBlk] = n;
Size[MaxBlk] = n - L[MaxBlk] + 1;
for (int i = 1; i <= m; ++i)
{
scanf("%d%d", &Q[i].l, &Q[i].r);
Q[i].Idx = i;
Q[i].v = Q[i].l / BlkSize;
}
sort(Q + 1, Q + m + 1, Cmp);
for (int i = Q[1].l; i <= Q[1].r; ++i) Add_Num(A[i]);
Ans[Q[1].Idx] = Get_Ans();
for (int i = 2; i <= m; ++i)
{
if (Q[i].r <= Q[i - 1].l)
{
Pull(0, Q[i - 1].l, Q[i].l);
Pull(1, Q[i - 1].r, Q[i].r);
}
else
{
Pull(1, Q[i - 1].r, Q[i].r);
Pull(0, Q[i - 1].l, Q[i].l);
}
Ans[Q[i].Idx] = Get_Ans();
}
for (int i = 1; i <= m; ++i) printf("%d\n", Ans[i]);
return 0;
}
[BZOJ 3585] mex 【莫队+分块】的更多相关文章
- Bzoj 3339: Rmq Problem && Bzoj 3585: mex 莫队,树状数组,二分
3339: Rmq Problem Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 833 Solved: 397[Submit][Status][D ...
- [BZOJ3585]mex(莫队+分块)
显然可以离线主席树,这里用莫队+分块做.分块的一个重要思想是实现修改与查询时间复杂度的均衡,这里莫队和分块互相弥补. 考虑暴力的分块做法,首先显然大于n的数直接忽略,于是将值域分成sqrt(n)份,每 ...
- bzoj 3585 mex - 线段树 - 分块 - 莫队算法
Description 有一个长度为n的数组{a1,a2,...,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. Input 第一行n,m. 第二行为n个数. 从第三行开始,每行一个询问 ...
- 【BZOJ3339&&3585】mex [莫队][分块]
mex Time Limit: 20 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description 有一个长度为n的数组{a1,a2,. ...
- [BZOJ 3236] [Ahoi2013] 作业 && [BZOJ 3809] 【莫队(+分块)】
题目链接: BZOJ - 3236 BZOJ - 3809 算法一:莫队 首先,单纯的莫队算法是很好想的,就是用普通的第一关键字为 l 所在块,第二关键字为 r 的莫队. 这样每次端点移动添加或删 ...
- 【BZOJ3585/3339】mex 莫队算法+分块
[BZOJ3585]mex Description 有一个长度为n的数组{a1,a2,...,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. Input 第一行n,m. 第二行为n个数. ...
- Bzoj 3236: [Ahoi2013]作业 莫队,分块
3236: [Ahoi2013]作业 Time Limit: 100 Sec Memory Limit: 512 MBSubmit: 1113 Solved: 428[Submit][Status ...
- 莫队+分块 BZOJ 3809
3809: Gty的二逼妹子序列 Time Limit: 80 Sec Memory Limit: 28 MBSubmit: 1634 Solved: 482[Submit][Status][Di ...
- BZOJ_3585_mex && BZOJ_3339_Rmq Problem_莫队+分块
BZOJ_3585_mex && BZOJ_3339_Rmq Problem_莫队+分块 Description 有一个长度为n的数组{a1,a2,...,an}.m次询问,每次询问一 ...
随机推荐
- 全文索引(三)lucene 分词 Analyzer
分词: 将reader通过阅读对象Analyzer字处理,得到TokenStream处理流程被称为分割. 该解释可能是太晦涩.查看示例,这个东西是什么感性的认识. 样品:一段文本"this ...
- MySQL 5.6 SQL 优化及 5.6手册
http://blog.chinaunix.net/uid-259788-id-4146363.html http://www.cnblogs.com/Amaranthus/p/4028687.htm ...
- Android BLE开发——Android手机与BLE终端通信初识
蓝牙BLE官方Demo下载地址: http://download.csdn.net/detail/lqw770737185/8116019参考博客地址: http://www.eoeandr ...
- CXF错误:Unsupported major.minor version 51.0,java.lang.UnsupportedClassVersionErro
CXF错误:Unsupported major.minor version 51.0 java.lang.UnsupportedClassVersionError >>>>&g ...
- mysql case when then else end 用法
select case when 判断条件 then 输出结果 else 输出结果 end from table
- 百度,人人,新浪,腾讯等分享Js代码
<!-- Baidu Button BEGIN --> <div id="bdshare" class=" ...
- Memento 模式
Memento 模式的关键就是要在不破坏封装行的前提下,捕获并保存一个类的内部状态,这样就可以利用该保存的状态实施恢复操作. /////////Originator.h//////////////// ...
- C++线程类的封装
简单的C++线程操作的封装,使用了智能指针管理对象的释放. 可运行对象基类 class SimpleRunable:public RefCountedBase { public: SimpleRuna ...
- [Lua]索引极致,form.lua
local form = {_tag = 'form'} function form.build(tag, super) local target = { _tag = tag, _super = s ...
- 说说http请求
为什么做web前端要了解http标准?因为浏览器要从服务端获取网页,网页也可能将信息再提交给服务器,这其中都有http的连接.web系统既然和http链接有瓜葛,你就必须去了解它.我将从一下几个方面讲 ...