分块思想其实是一种暴力
还是 【线段树1】洛谷模板
我们可以把它分成 (sqrt n, sqrt n,..., sqrt n) 这样的一个一个块。
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5 + 10, M = 350;
int id[N], w[N];
ll sum[M], lz[M];
int n, m, len;
void updt(int l, int r, int v) {
if (id[l] == id[r]) {
for (int i = l; i <= r; i++) w[i] += v, sum[id[i]] += v;
return;
}
int i = l, j = r;
while (id[i] == id[l])w[i] += v, sum[id[i]] += v, i++;
while (id[j] == id[r])w[j] += v, sum[id[j]] += v, j--;
for (int k = id[i]; k <= id[j]; k++)sum[k] += 1ll * len * v, lz[k] += v;
}
ll query(int l, int r) {
ll res = 0;
if (id[l] == id[r]) {
for (int i = l; i <= r; i++) res += w[i] + lz[id[i]];
return res;
}
int i = l, j = r;
while (id[i] == id[l]) res += w[i] + lz[id[i]], i++;
while (id[j] == id[r]) res += w[j] + lz[id[j]], j--;
for (int k = id[i]; k <= id[j]; k++) res += sum[k];
return res;
}
int main() {
scanf("%d%d", &n, &m);
len = sqrt(n);
for (int i = 1; i <= n; i++) scanf("%d", w + i), id[i] = i / len, sum[id[i]] += w[i];
while (m--) {
int op, a, b, c;
scanf("%d", &op);
if (op == 1) {
scanf("%d%d%d", &a, &b, &c);
updt(a, b, c);
}
else {
scanf("%d%d", &a, &b);
printf("%lld
", query(a, b));
}
}
}