实现分块就是将数据分成一个个区间(一般为sqrt(n),此时复杂度为n*sqrt(n))
那么实现:
首先处理出块中的各个数据:
sq=sqrt(n);//块长
for (int i = 1; i <= n; i++) {
bel[i] = min((i - 1) / sq + 1, sq);//数所在的块
}
for (int i = 1; i <= n; i++)ed[bel[i]] = i;//某个块的结束
for (int i = n; i >= 1; i--)st[bel[i]] = i;//某个块的起始
ed[sq] = n;//防止遗漏
for (int i = 1; i <= sq; i++) {
sz[i] = ed[i] - st[i] + 1;//某个块的大小
}
for (int i = 1; i <= n; i++) {
cin >> a[i]; sum[bel[i]] += a[i];//区间和
}
而修改块分为两种情况:
两端点都在一个块内(暴力处理)
else
处理整块(打标记,类似于线段树的lazy?)
两边的散块(暴力处理)
查询与修改差不多:
两端点都在一个块内(暴力查询)
else
处理整块(算标记)
两边的散块(暴力查询)
现在就可以实现区间加减,查询了,如P3372 【模板】线段树 1 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include<bits/stdc++.h>
#include<iostream>
#define int long long
using namespace std;
int sq,a[114514], bel[114514], st[114514], ed[114514], sz[114514], mark[114514], sum[114514],n;
void add(int l, int r, int k) {
if (bel[l] == bel[r]) {
for (int i = l; i <= r; i++)a[i] += k, sum[bel[i]] += k;
return;
}
else {
for (int i = l; i <= ed[bel[l]]; i++) {
a[i] += k;
sum[bel[i]] += k;
}
for (int i = st[bel[r]]; i <= r; i++) {
a