数组分块简述
在某些情况下,我们可能需要暴力地处理数组的每一个数,数组分块提供了一种简单的优化来降低复杂度,使得原本的$O(n)$降为$O(\sqrt n)$,这可能不是最优解,但一定足够简单(事实上,在1e5范围内,$O(\log^2 n)$和$O(\sqrt n)$差距不大)。 这类问题的“整体”性质更弱,有时不存在高效的信息合并化简方法,需要在“批量”和“零散”之间找到平衡点。
- 基础形式
我们将一个数组分为形如下图的几段,每段大小为B,当然为了规范,如果$B \nmid n$,我们要在数组后面填充$inf$(在后面的一些处理中会用到这个)。对每次操作只需要对左右两个散块单独处理和对中间一些整块处理。
理解了分块的概念以后,你就可以开始着手尝试用分块去解决一些线段树问题了(虽然此时分块对比线段树不占优)。
例题
模板题
题目大意:区间上所有元素加一个数$k$;求区间所有元素的和。 对于这个问题,简单地开三个数组$a,s,v$ 分别表示:数组值;分块中除去标记的数组值和;标记:分块中的每个元素 + k。
参考代码: 每个块的左右边界可以用结构体记录下来,也可以直接计算,这里采用的是直接计算的方式。
|
|
分块的大小可以人为确定,需要计算时间复杂度后再确定。此题中理论时间复杂度为$O(q (B + n / B))$, 另$B = \sqrt n$,得到最优时间复杂度$O(q \sqrt n)$。
教主的魔法
题目大意:1、区间加;2、求区间大于$c$的元素个数。
首先来思考一下如何找出一个整块中大于$c$的元素个数 …… 如果一个整块中的元素有序,那么是不是可以二分。
在上题中我们用$s$来维护区间和,现在我们用$s$来维护区间的有序数组。那么一个区间内大于$c$的元素个数就等于散块大于$c$的个数 + 每个整块中大于$c$的个数(这部分用lower_bound来处理)。单次询问时间复杂度为$O((n/B) log B + B)$。
在来思考一下区间加,由于需要额外维护一个有序数组,每次加操作可以对散块进行暴力排序,整块就在标记上加值,单词加的时间复杂度为$O(B log B + n / B)$。
关于B的取值问题,首先应该考虑平衡两种操作的时间复杂度,其次应该考虑整块的时间复杂度和散块部分的时间复杂度,具体而言就是让两者相等求出B。比如此题中对散块重新排序可以优化成提取有序的两部分(有改动和无改动)再merge,此时加操作的时间复杂度就降为$O(B + n / B)$,发现这个复杂度是恒小于询问操作的复杂度的,此时就应该考虑适当增大B的大小,可以对$(n / B) log B + B$ 求导计算出极值,也可以用三分来求,事实上这个值约等于$\sqrt{n\log \sqrt n}$。
参考代码(不加优化):
|
|
稍稍写一下归并的代码(给一个结构体写的板子)
|
|
由乃打扑克
给你一个长为 $n$ 的序列 $a$,需要支持 $m$ 次操作,操作有两种: 1、查询区间 $[l,r]$ 的第 $k$ 小值。 2、区间 $[l,r]$ 加上 $k$。
分块 + 整体二分
第$k$小的值$x$就相当于区间内存在$k-1$个数小于等于$x$,并且求这个值符合二分的规则,故可以整体二分确定$x$的大小,具体的check方法与上一例题一模一样。
几个优化: 1. 二分前将左右两块散块合并,这样可以用$O(log\ B)$来代替对整个散块遍历的$O(B)$ 2. 二分前计算出二分的上下界,以减少二分次数。 复杂度分析: add 时间复杂度$O(B + n / B)$ query 时间复杂度$O(B + (n / B)log\ B\ log\ w)$ ($log\ w$ 是二分是次数,大概为$20-30$)。
确定块长:理论上复杂度的计算应该是查询时间复杂度 对$B$求偏导得到的,但是按照理论来算的话,这题这么做是可以被卡掉的。于是需要调亿点点块长,下面这份代码块长取$912$可以拿到$82pts$(已经不想扣常数了)。
|
|
弹飞绵羊
有$n$个点,每个点都有一个值$k$,第$i$个点会通过一次弹射到$i + k_i$上,直到点不存在。两种操作,一种询问第$i$个点一共会经历几次弹射,另一种修改$k_i$。
如果不存在修改操作,那么只需要预处理出所有点的答案,每次查询只需要$O(1)$的复杂度就可以求出解。而修改的操作是$O(n)$的,因此需要一种方法来平衡两种操作。发现可以将所有点任意地分割成$x$段,每一小段中的每个点都存在一个$k’_i$从所在段中弹飞,并且落到另一段中的某个点,因此可以记录每个段中每个点从所在段弹飞的所需的次数以及落点,此时每次修改只需要修改所在块即可。故得出解:将$n$个点分成$\sqrt n$段,同时记录次数和位置,修改就重构块,查询就对该点在所有块中的次数求和。两种操作的时间复杂度均为$\sqrt n$。
|
|
- 有时间再补 简单的数列题 作诗 [Violet]蒲公英 任务分配问题