树状数组plus
设 \(A_i\) 是原数组, \(d_i = A_i - A_{i-1}\) 是 \(A\) 的差分数组
有
\[S_n = \sum_{i=1}^nA_i = d_1 + \\d_1 + d_2 +\\ d_1 + d_2 + d_3 + \\ ... \\d_1 + d_2 + d_3 + d_4 + ... + d_n \\ = n (d_1 + d_2 + ... + d_n) - \sum_{i=1}^nd_i(i-1)
\]
设 \(B_i = d_i(i-1)\)
则
\[S_n = n\sum d - \sum B
\]
而当一段区间 \([L,R]\) 一起加上 \(x\) 的时候,
对于 \(d\) 来说,只有 \(d_L\) 和 \(d_{R+1}\) 发生了变化
对于 \(B\) 来说,也是同理,所以可以开两个树状数组来进行维护
/*
* @Author: zhl
* @Date: 2020-11-17 10:33:57
*/
#include<bits/stdc++.h>
using ll = long long;
using namespace std;
const int N = 1e5 + 10;
int n, m;
struct{
ll C[N][2]; // 0 是差分d_i , 1 是 d_i * (i - 1)
void add(int pos, ll val, int o) {
for (; pos <= n; pos += (-pos) & pos) C[pos][o] += val;
}
ll ask(int pos, int o) {
ll ans = 0;
for (; pos; pos -= (-pos) & pos) ans += C[pos][o];
return ans;
}
void updt(int l, int r, int x) {
add(l, x, 0); add(r + 1, -x, 0);
add(l, x * (l - 1), 1); add(r + 1, -x * (r), 1);
}
ll query(int l, int r) {
ll R = r * ask(r, 0) - ask(r, 1);
ll L = (l - 1) * ask(l - 1, 0) - ask(l - 1, 1);
return R - L;
}
}BIT;
int main() {
scanf("%d%d", &n, &m);
int pre = 0;
for (int i = 1; i <= n; i++) {
int x; scanf("%d", &x);
BIT.add(i,x - pre,0);
BIT.add(i, 1ll * (x - pre)* (i - 1), 1);
pre = x;
}
while (m--) {
int op, a, b, x;
scanf("%d", &op);
if (op == 1) {
scanf("%d%d%d", &a, &b, &x);
BIT.updt(a, b, x);
}
else {
scanf("%d%d", &a, &b);
printf("%lld\n", BIT.query(a, b));
}
}
}