希望对你有帮助
```
static int n, m;
static int[] a;
static int[] pre, end;//记录第i块的第一个元素和最后一个元素的索引
static int[] sum;//记录第i块的区间和
static int[] pos;//表示第i个元素所在的块
static int[] add;//定义变化标记
static void init() throws IOException {
b = (int) sqrt(n);//计算块大小
t = n / b;
if (n % b != 0) t++;
a = new int[n + 1];
for (int i = 1; i <= n; ++i) a[i] = read.nextInt();
pre = new int[n + 1];
end = new int[n + 1];
sum = new int[n + 1];
add = new int[n + 1];
pos = new int[n + 1];
for (int i = 1; i <= t; ++i) {
pre[i] = (i - 1) * b + 1;
end[i] = i * b;
}
end[t] = n;
for (int i = 1; i <= n; ++i) pos[i] = (i - 1) / b + 1;
//求出每一块的和
for (int i = 1; i <= t; ++i)
for (int j = pre[i]; j <= end[i]; ++j) {
sum[i] += a[j];
}
}
//实现区间修改函数
static void modify(int l, int r, int 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 <= end[p]; ++i) a[i] += d;
sum[p] += (d * (end[p] - l + 1));
for (int i = pre[q]; i <= r; ++i) a[i] += d;
sum[q] += (d * (r - pre[q] + 1));
}
}
//区间查询
static long query(int l, int r) {
int p = pos[l], q = pos[r];
long ans = 0;
if (p == q) {
for (int i = l; i <= r; ++i) ans += a[i];
ans += ((long) add[p] * (r - l + 1));
} else {
for (int i = p + 1; i <= q - 1; ++i) ans += (sum[i] + (long) add[i] * (end[i] - pre[i] + 1));
for (int i = l; i <= end[p]; ++i) ans += a[i];
ans += ((long) add[p] * (end[p] - l + 1));
for (int i = pre[q]; i <= r; ++i) ans += a[i];
ans += ((long) add[q] * (r - pre[q] + 1));
}
return ans;
}
static int b, t;
public static void main(String[] args) throws Exception {
n = read.nextInt();
m = read.nextInt();
init();
while (m-- > 0) {
int opt = read.nextInt();
if (opt == 1) {
int x = read.nextInt(), y = read.nextInt(), k = read.nextInt();
modify(x, y, k);
} else {
pr.write(query(read.nextInt(), read.nextInt()) + "\n");
}
}
pr.close();
}
```
by Molie @ 2023-11-23 20:18:35