[BZOJ 3585] mex 【莫队+分块】

时间:2022-08-31 18:43:21

题目链接: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 【莫队+分块】的更多相关文章

  1. Bzoj 3339&colon; Rmq Problem &amp&semi;&amp&semi; Bzoj 3585&colon; mex 莫队&comma;树状数组&comma;二分

    3339: Rmq Problem Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 833  Solved: 397[Submit][Status][D ...

  2. &lbrack;BZOJ3585&rsqb;mex&lpar;莫队&plus;分块&rpar;

    显然可以离线主席树,这里用莫队+分块做.分块的一个重要思想是实现修改与查询时间复杂度的均衡,这里莫队和分块互相弥补. 考虑暴力的分块做法,首先显然大于n的数直接忽略,于是将值域分成sqrt(n)份,每 ...

  3. bzoj 3585 mex - 线段树 - 分块 - 莫队算法

    Description 有一个长度为n的数组{a1,a2,...,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. Input 第一行n,m. 第二行为n个数. 从第三行开始,每行一个询问 ...

  4. 【BZOJ3339&amp&semi;&amp&semi;3585】mex &lbrack;莫队&rsqb;&lbrack;分块&rsqb;

    mex Time Limit: 20 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 有一个长度为n的数组{a1,a2,. ...

  5. &lbrack;BZOJ 3236&rsqb; &lbrack;Ahoi2013&rsqb; 作业 &amp&semi;&amp&semi; &lbrack;BZOJ 3809&rsqb; 【莫队(&plus;分块)】

    题目链接: BZOJ - 3236   BZOJ - 3809 算法一:莫队 首先,单纯的莫队算法是很好想的,就是用普通的第一关键字为 l 所在块,第二关键字为 r 的莫队. 这样每次端点移动添加或删 ...

  6. 【BZOJ3585&sol;3339】mex 莫队算法&plus;分块

    [BZOJ3585]mex Description 有一个长度为n的数组{a1,a2,...,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. Input 第一行n,m. 第二行为n个数. ...

  7. Bzoj 3236&colon; &lbrack;Ahoi2013&rsqb;作业 莫队&comma;分块

    3236: [Ahoi2013]作业 Time Limit: 100 Sec  Memory Limit: 512 MBSubmit: 1113  Solved: 428[Submit][Status ...

  8. 莫队&plus;分块 BZOJ 3809

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

  9. BZOJ&lowbar;3585&lowbar;mex &amp&semi;&amp&semi; BZOJ&lowbar;3339&lowbar;Rmq Problem&lowbar;莫队&plus;分块

    BZOJ_3585_mex && BZOJ_3339_Rmq Problem_莫队+分块 Description 有一个长度为n的数组{a1,a2,...,an}.m次询问,每次询问一 ...

随机推荐

  1. 记一次CSR上线及总结

    终于到上线的时候了,可以好好休息了.放松了,但在没有经过用户确认之前,一切皆有可能发生...... 经历: 项目终于完成,上线文档已准备就绪,等待上线时刻. 在上线之前,忘记了解目前环境的部署架构,注 ...

  2. 深入学习 memset 函数

    最近,和同学讨论了一下memset函数,趁着周五空闲做一总结. memset函数最常用的功能就是初始化数组了(主要是置零),如 #include <iostream> #include & ...

  3. 【poj 3461】Oulipo(字符串--KMP)

    题意:求子串在文本串中出现了多少次. 解法:使用KMP的next[ ]和tend[ ]数组计数. #include<cstdio> #include<cstdlib> #inc ...

  4. Apache 日志分析&lpar;二&rpar;

    01.查看IP cat access_log | awk ‘{print $1}’   02.对IP排序 cat access_log | awk ‘{print $1}’ | sort   03.打 ...

  5. SQL注入&lpar;一&rpar; - 入门篇

    什么是SQL注入 可能大家还不是对SQL注入这个概念不是很清楚,简单地说,SQL注入就是攻击者通过正常的WEB页面,把自己SQL代码传入到应用程序中,从而通过执行非程序员预期的SQL代码,达到窃取数据 ...

  6. python小技巧01递归解释内嵌

    现假设有一份机器人配件名单 list[头部,躯干,肢体] 头部这个list又有鼻子眼睛嘴巴这些小零件 肢体这个list有胳膊,肩膀,手.手这个list又有3种手指 所以这个list详细写出是: lis ...

  7. EF中打印出执行sql语句

    不用非得去 SQL Server Profiler 中查看了 方法如下: dbContext.Database.Log+=c=>Console.WriteLine(c)

  8. &lbrack;CTCI&rsqb; 最小调整有序

    最小调整有序 题目描述 有一个整数数组,请编写一个函数,找出索引m和n,只要将m和n之间的元素排好序,整个数组就是有序的.注意:n-m应该越小越好,也就是说,找出符合条件的最短序列. 给定一个int数 ...

  9. Dubbo背景和简介

    转载出处 Dubbo开始于电商系统,因此在这里先从电商系统的演变讲起. 单一应用框架(ORM) 当网站流量很小时,只需一个应用,将所有功能如下单支付等都部署在一起,以减少部署节点和成本. 缺点:单一的 ...

  10. Oracle中-事务-序列-视图-数据类型笔记

    事务(Transaction) 事务(Transaction)是一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位,是数据库环境中的逻辑工作单位. 事务是为了保证数据库的完整性 在o ...