分块
分块算法简介
分块(Square Root Decomposition)是一种将数据分成若干块,通过预处理和分块处理来优化区间操作的数据结构。它在信息学奥赛中广泛应用于解决区间查询和更新问题,是平衡代码复杂度和时间效率的利器。
分块的核心思想是将数据分成大小为√n的块,每个块维护一些预处理信息(如区间和、最大值等),从而将区间操作的时间复杂度从O(n)降低到O(√n)。
分块的核心思想
- 数据分块:将长度为n的数组分成√n个块,每个块的大小为√n。
- 预处理:对每个块维护一些统计信息(如区间和、最大值等)。
- 区间操作:
- 对于完整的块,直接利用预处理信息快速计算。
- 对于不完整的块(残块),暴力处理。
- 复杂度平衡:通过分块,将区间操作的时间复杂度从O(n)降低到O(√n)。
分块的实现步骤
以区间求和为例
const int MAXN = 1e5 + 5;
const int BLOCK_SIZE = 350; // √1e5 ≈ 316,取稍大值
int a[MAXN]; // 原始数组
int sum[BLOCK_SIZE]; // 每个块的和
int tag[BLOCK_SIZE]; // 每个块的懒标记
int bel[MAXN]; // 每个元素所属的块
// 初始化分块
void init(int n) {
int block_num = (n + BLOCK_SIZE - 1) / BLOCK_SIZE;
for (int i = 1; i <= n; i++) {
bel[i] = (i - 1) / BLOCK_SIZE + 1;
sum[bel[i]] += a[i];
}
}
// 区间更新
void update(int l, int r, int val) {
// 处理左残块
while (l <= r && bel[l] == bel[l - 1]) {
a[l] += val;
sum[bel[l]] += val;
l++;
}
// 处理整块
while (bel[l] < bel[r]) {
sum[bel[l]] += val * BLOCK_SIZE;
tag[bel[l]] += val;
l += BLOCK_SIZE;
}
// 处理右残块
while (l <= r) {
a[l] += val;
sum[bel[l]] += val;
l++;
}
}
// 区间查询
int query(int l, int r) {
int res = 0;
// 处理左残块
while (l <= r && bel[l] == bel[l - 1]) {
res += a[l] + tag[bel[l]];
l++;
}
// 处理整块
while (bel[l] < bel[r]) {
res += sum[bel[l]] + tag[bel[l]] * BLOCK_SIZE;
l += BLOCK_SIZE;
}
// 处理右残块
while (l <= r) {
res += a[l] + tag[bel[l]];
l++;
}
return res;
}

浙公网安备 33010602011771号