一、前言
对线段树还挺熟悉的我之前却从没写过分块的题(?)。然后兴致一来就决定搜点练习,找到了来自hzwer的《数列分块入门1-9》,觉得挺不错的,于是决定做做。
二、概念 / 作用
概念:将数列等分为若干个不相交的区间,每一个区间称为一个块。
作用:优化算法,降低复杂度。具体如何降低,在下面的题目中会逐步提及。题目呈难度递增趋势。
三、题目 / 代码
题面:给出一个长为 n 的数列,以及 n 个操作,操作涉及区间加法,单点查询。
挺多数据结构均能实现的经典题目,譬如线段树。这里我们用分块来做。将 n 个元素等分为若干块,比如{1, 4, 8, 2, 9, 6, 3, 7, 5},等分为3块,则第一块包含的数据为{1, 4, 8},第二、三块以此类推。我们给每一个块增加一个加法标记,对于每次的区间[l, r]加法操作,直接对块进行标记叠加。
l, r必然不一定是块的边界,也就意味着左右端点可能在块的中间,直接一个个暴力增加。设块的元素个数为m,标记块个数至多n / m个,暴力增加元素个数至多2m个,复杂度分析:O(n / m) + O(m),根据均值不等式,可证明m = √n时存在最低复杂度。故我们以下所有分块大小均默认为√n。
询问就很轻松了,直接返回元素的值加上所在区间的标记。
代码:
1 #include
2 using namespacestd;3
4 #define MAXN 50005
5