树状数组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 = nsum d - sum B ]

而当一段区间 ([L,R]) 一起加上 (x) 的时候,

对于 (d) 来说,只有 (d_L)(d_{R+1}) 发生了变化

对于 (B) 来说,也是同理,所以可以开两个树状数组来进行维护

【模板】线段树1

/*
 * @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
", BIT.query(a, b));
		}
	}
}
原文地址:https://www.cnblogs.com/sduwh/p/13994080.html