分块入门详解(比较全面)

最近写了几个分块,顺便做一下笔记。

什么是分块

分块是一种数据结构。。

有许多数据结构都是 log 数据结构,比如线段树,树状数组等等。他们复杂度优秀,但是都是树形结构,有较大的思维难度和局限性。那么有没有什么复杂度一般,但是非树形的数据结构呢?

有的,就是分块。

分块的思路是把数据分成一个个的小块。设每块长为 S。举个栗子:

1, 1, 4, 5, 1, 4 (S = 2)

那么我们就可以把他分成

1, 1 | 4, 5 | 1, 4

我们成功把他分成了三个小块。

对于每个询问 [l,r],它会跨越许多小块和整块。比如对于刚才那个数据:

1, 1 | 4, 5 | 1, 4 (l = 2, r = 5, S = 2)
   |          |
   l -------- r

l, r 跨越了第一块的后半个,第二块和第三块的前半个。

对于整块,我们一般可以用打懒标记之类的方法来搞,一共有 nS 个整块,所以复杂度最坏也是 O(nS)。对于散块来说,最多会有一左一右两个散块,长度最多为 2S,对他们进行暴力操作,复杂度最坏为 O(S)。考虑常数,总复杂度为 O(2S+nS)。(虽然 O 里面不应该加常数)。根据均值不等式,当 S=22n。通常我们取 S=n,单次操作复杂度稳定在 O(n) 级别。

分块怎么写

首先先说一下分块的几个重要操作:

  1. 定位操作。get(x) 函数返回 x 所处的块的编号。可以这样写 int get(x) { return (int)x / S; }
  2. 查询端点。getl/getr,返回当前块的左、右端点。可以这样写(前提是你的 get 函数和我一样。)
int getl(int x) { return S * x + (x == 0); }
int getr(int x) { return min(n, (x + 1) * S - 1); }

数列分块入门1 举个栗子。

题意: 给定长度为 n 的数列,进行 n 次操作。操作涉及区间加法,单点查询。

这种题当然可以 线段树 / 树状数组,但是今天我们要用分块来写。按照上面我们说的。借鉴线段树的思路,我们可以维护一个 add 懒标记,来维护当前块应该加上几。

现在假设我们修改的区间是 [l,r],可能有下面几种情况。

  • 左右端点在同一个块里。我们遍历 lr,暴力加即可。复杂度 O(n)
  • 左右端点不在同一个块里。我们可以遍历中间的整块并打上懒标记。由于块数不超过 O(n) 个,所以复杂度也不高。对于不在整块内的边角,直接暴力加就可以。

核心代码

int get(int x) { return x / S; } // 定位当前点在哪个块
void modify(int l, int r, int v) { // 修改操作
	int ls = get(l), rs = get(r);
	if (ls == rs) { for (int i = l; i <= r; i ++ ) w[i] += v; return; } // 在同一个整块内
	int i, j;
	for (i = l; get(i) == ls; i ++ ) w[i] += v; // 处理边角
	for (j = r; get(j) == rs; j -- ) w[j] += v;
	for (int k = get(i); k <= get(j); k ++ ) // 处理整块。
		add[k] += v;
}

int main() {
	.......

	if (query node) printf("%d\n", w[r] + add[get(r)]);
	else modify(l, r, v);
}

其他例题

数列分块入门7

题意: 给出一个长为 n 的数列,以及 n 个操作,操作涉及区间乘法,区间加法,单点询问。

可以对照线段树2来做。对每个块维护加、乘懒标记。注意:懒标记更新的时候注意顺序,对散块操作的时候要重构整个块。

代码示例

数列分块入门2

题意: 给出一个长为 n 的数列,以及 n 个操作,操作涉及区间加法,询问区间内小于某个值 x 的元素个数。

分块常用的思想,就是在每个块内维护一个有序序列。加操作时可以打懒标记。查询操作可以直接块内二分。单次操作复杂度 O(nlogn)lognlogn 同阶)

代码示例

数列分块入门5

这道题带插入怎么办呢?块状链表隆重登场!!

块状链表可以看一下我写的博客 块状链表详解

剩下的就不讲了吧,再放几道例题。

例题

  1. 数列分块全系列

  2. 某些线段树题(比如洛谷线段树模板)

  3. 其他题目,如 Luogu 分数统计

以后可能还会加例题。先挖个坑。

posted @   Link-Cut-Y  阅读(136)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
点击右上角即可分享
微信分享提示