30.分块
分块
算法思想
分块不是一种数据结构,而是一种思想
通过对原数据的适当划分,并在划分后的每一个块上预处理部分信息,从而较一般的暴力算法取得更优的时间复杂度。

实现
具体来说分块的基本要素如下:
- 块的大小:
,一般情况下都定义 - 块的数量:
- 块的左右边界,定义数组
,分别表示第 个块的第一个和最后一个元素的位置,显然有 - 每个元素属于的块
表示第 个元素所在的块,有
下面是常见分块代码实现
int block = sqrt(n), t = n / block + (n % block != 0); // t 表示块数
for (int i = 1; i <= t; i++)
st[i] = (i - 1) * block + 1, ed[i] = i * block;
ed[t] = n;
for (int i = 1; i <= n; i++)
belong[i] = (i - 1) / block + 1;
用分块解决区间问题很方便,定义区间有关的数组,
例如我们需要求区间和,就定义
for (int i = 1; i <= num; i++)
for (int j = st[i]; j <= ed[i]; j++)
sum[j] += a[j];
然后
考虑区间修改:将
- 如果区间
在某个块内,直接暴力修改,然后更新 ,计算次数为 - 如果跨越了多个块,假设被
包含了 个块,更新 对于两头没有完全包含的就暴力处理,计算次数为
考虑区间查询:输出
- 区间
在一个块内,暴力累计,最后加上 ,答案就是 ,计算次数为 - 区间
跨越了多个块,在被 那些完全包含的块内, ,两头的情况暴力处理 ,计算次数为
所以块的大小