树状数组,一个树状数组会T, 采用两个树状数组。
一个存a[1] + a[2] + a[3] + ... a[n -1] + a[n] ;
另一个存n * a[1] + (n-1) * a[2] + (n-2) * a[3] +... 2 * a[n-1] + a[n] ;
ans1 = getsum1(r) - getsum1(l-1) // a[l] + a[l + 1] + ... a[r];
ans2 = getsum2(r) - getsum(l-1) // (n - l + 1) * a[l] + (n - l) *a[l + 1] + ... (n-r+1) * a[r];
ans = ans2 - (n - r) * ans1; // n - r 自己去推一下
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int MaxN = 1e5 + 5;
long long a1[MaxN], a2[MaxN];
int n, q, m;
int lowbit(int x) {
return x & (-x);
}
void update1(int x, long long val) {
for(int i = x; i <= n; i += lowbit(i))
a1[i] += val;
}
void update2(int x, long long val) {
for(int i = x; i <= n; i += lowbit(i)) {
a2[i] += val;
}
}
long long getsum1(int x) {
long long ans = 0;
for(int i = x; i > 0; i -= lowbit(i))
ans += a1[i];
return ans;
}
long long getsum2(int x) {
long long ans = 0;
for(int i = x; i > 0; i -= lowbit(i))
ans += a2[i];
return ans;
}
int main() {
scanf("%d %d", &n, &q);
for(int i = 1; i <= n; i++) {
long long pp;
scanf("%lld", &pp);
update1(i, pp);
update2(i, pp * (n-i+1));
}
//for(int i = 1; i <= n; i++) printf("%lld %lld
", a1[i], a2[i]);
while(q--) {
int op, l, r;
scanf("%d%d%d", &op, &l, &r);
if(op == 1) {
long long ans1 = getsum2(r) - getsum2(l-1);
long long ans2 = getsum1(r) - getsum1(l-1);
long long ans = ans1 - (n-r) * ans2;
printf("%lld
", ans);
}
else {
long long tem = getsum1(l) - getsum1(l-1);
update1(l, r - tem);
update2(l, (r - tem) * (n-l+1));
}
}
return 0;
}