数列分块入门 9

First Post:

Last Update:

Word Count:
964

Read Time:
4 min

Page View: loading...

给定一个长为 的序列, 次询问区间最小众数。


algo 1

首先要离散化。

考虑分块。

令块长为 ,我们预处理以下内容:

  • 任意两块之间的最小众数,总的时间复杂度 ,空间复杂度
  • 任意两块之间每个数的出现次数,这个前缀和处理,时间复杂度为 ,空间复杂度与时间同阶。

考虑如何处理查询。对于每次查询,涉及的数分为 整块间的数散块内的数。对于整块内的数,显然可能成为众数的就是这些数的众数;对于散块内的数,每一个数都可能成为众数,因为我们不知道它们在整块间的出现情况。

我们对于这 个数,检查它们出现的次数。对于散块,我们暴力累计;对于整块,我们有预处理时统计的计数数组。

因此单次查询的复杂度是 的。

发现取 可以达到理论最优复杂度。


有一些实现细节。

首先你在查询时需要一个计数数组来维护每个数出现的次数,你发现这个东西不能每次重新建一个,否则单次就 了。

同理你也不能每次使用后清空,因此你需要记录哪些数出现了,用于最终撤销对计数数组的修改。

然后你发现你需要对每个出现过的数处理它们在块间出现过几次,但你记录哪些数出现的时候没法去重,这时排序去重又要多一个

你发现你可以利用计数数组,扫一遍所有要记录的数,仅当它是最后一次出现,才记录它的贡献。

当然,你也可以使用 unordered_map,这样甚至不需要最开始的离散化,但是常数可能略大。