分块
# 分块
# 算法思想
分块不是一种数据结构,而是一种思想
通过对原数据的适当划分,并在划分后的每一个块上预处理部分信息,从而较一般的暴力算法取得更优的时间复杂度。
# 实现
具体来说分块的基本要素如下:
- 块的大小:,一般情况下都定义
- 块的数量:
- 块的左右边界,定义数组 ,分别表示第 个块的第一个和最后一个元素的位置,显然有
- 每个元素属于的块 表示第 个元素所在的块,有
下面是常见分块代码实现
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;
1
2
3
4
5
6
2
3
4
5
6
用分块解决区间问题很方便,定义区间有关的数组,
例如我们需要求区间和,就定义 表示第 个块的 的和,并预处理出初始值
for (int i = 1; i <= num; i++)
for (int j = st[i]; j <= ed[i]; j++)
sum[j] += a[j];
1
2
3
2
3
然后 表示第 个块的增量标记,初始为
考虑区间修改:将 内每个数加上
- 如果区间 在某个块内,直接暴力修改,然后更新 ,计算次数为
- 如果跨越了多个块,假设被 包含了 个块,更新 对于两头没有完全包含的就暴力处理,计算次数为
考虑区间查询:输出 内每个数的和
- 区间 在一个块内,暴力累计,最后加上 ,答案就是 ,计算次数为
- 区间 跨越了多个块,在被 那些完全包含的块内,,两头的情况暴力处理 ,计算次数为
所以块的大小 为多少时最优,每次操作的次数为 或 , 最大 ,最差时间复杂度为 按照基本不等式 时最优,此时
上次更新: 2024/09/14, 12:53:16