题目链接: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次询问,每次询问一 ...
随机推荐
-
记一次CSR上线及总结
终于到上线的时候了,可以好好休息了.放松了,但在没有经过用户确认之前,一切皆有可能发生...... 经历: 项目终于完成,上线文档已准备就绪,等待上线时刻. 在上线之前,忘记了解目前环境的部署架构,注 ...
-
深入学习 memset 函数
最近,和同学讨论了一下memset函数,趁着周五空闲做一总结. memset函数最常用的功能就是初始化数组了(主要是置零),如 #include <iostream> #include & ...
-
【poj 3461】Oulipo(字符串--KMP)
题意:求子串在文本串中出现了多少次. 解法:使用KMP的next[ ]和tend[ ]数组计数. #include<cstdio> #include<cstdlib> #inc ...
-
Apache 日志分析(二)
01.查看IP cat access_log | awk ‘{print $1}’ 02.对IP排序 cat access_log | awk ‘{print $1}’ | sort 03.打 ...
-
SQL注入(一) - 入门篇
什么是SQL注入 可能大家还不是对SQL注入这个概念不是很清楚,简单地说,SQL注入就是攻击者通过正常的WEB页面,把自己SQL代码传入到应用程序中,从而通过执行非程序员预期的SQL代码,达到窃取数据 ...
-
python小技巧01递归解释内嵌
现假设有一份机器人配件名单 list[头部,躯干,肢体] 头部这个list又有鼻子眼睛嘴巴这些小零件 肢体这个list有胳膊,肩膀,手.手这个list又有3种手指 所以这个list详细写出是: lis ...
-
EF中打印出执行sql语句
不用非得去 SQL Server Profiler 中查看了 方法如下: dbContext.Database.Log+=c=>Console.WriteLine(c)
-
[CTCI] 最小调整有序
最小调整有序 题目描述 有一个整数数组,请编写一个函数,找出索引m和n,只要将m和n之间的元素排好序,整个数组就是有序的.注意:n-m应该越小越好,也就是说,找出符合条件的最短序列. 给定一个int数 ...
-
Dubbo背景和简介
转载出处 Dubbo开始于电商系统,因此在这里先从电商系统的演变讲起. 单一应用框架(ORM) 当网站流量很小时,只需一个应用,将所有功能如下单支付等都部署在一起,以减少部署节点和成本. 缺点:单一的 ...
-
Oracle中-事务-序列-视图-数据类型笔记
事务(Transaction) 事务(Transaction)是一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位,是数据库环境中的逻辑工作单位. 事务是为了保证数据库的完整性 在o ...