题目是 模板线段树1
按照老师的思路写的
感觉没问题
样例可以过
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100010;
long long a[MAXN], sum[MAXN], add[MAXN];
int L[MAXN], R[MAXN], pos[MAXN], n, m, t;
void change(int l, int r, long long d) {
int p = pos[l], q = pos[r];
if (p == q) { // 在同一个区间内
for (int i = l; i <= r; ++i) a[i] += d;
sum[p] = d * (r - l + 1); // 高斯求和
}
else { // 不在同一个区间
for (int i = p + 1; i <= q - 1; ++i) add[i] += d;
for (int i = l; i <= R[p]; ++i) a[i] += d;
sum[p] += (R[p] - l + 1) * d;
for (int i = L[q]; i <= r; ++i) a[i] += d;
sum[p] += (r - L[q] + 1) * d;
}
}
long long ask(int l, int r) {
int p = pos[l], q = pos[r];
long long ans = 0;
if (p == q) {
for (int i = l; i <= r; ++i) ans += a[i];
ans += add[p] * (r - l + 1);
}
else {
for (int i = p + 1; i <= q - 1; ++i) ans += sum[i] + add[i] * (R[i] - L[i] + 1);
for (int i = l; i <= R[p]; ++i) ans += a[i];
ans += (R[p] - l + 1) * add[p];
for (int i = L[q]; i <= r; ++i) ans += a[i];
ans += (r - L[q] + 1) * add[q];
}
return ans;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) scanf("%lld", &a[i]);
t = sqrt(n);
for (int i = 1; i <= t; ++i) {
L[i] = (i - 1) * sqrt(n) + 1;
R[i] = i * sqrt(n);
}
if (R[t] < n) ++t, L[t] = R[t - 1] + 1, R[t] = n;
for (int i = 1; i <= n; ++i)
for (int j = L[i]; j <= R[i]; ++j)
pos[j] = i, sum[i] += a[j];
while (m--) {
int opt, x, y;
long long k;
scanf("%d%d%d", &opt, &x, &y);
if (opt == 1) {
scanf("%lld", &k);
change(x, y, k);
}
else printf("%lld\n", ask(x, y));
}
return 0;
}