题目来源:http://poj.org/problem?id=3468
线段树做法:https://blog.csdn.net/moon_sky1999/article/details/78428165
详解树状数组区间修改、查询操作的博客:
代码:
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn=1e5+10;
ll c1[maxn],c2[maxn],a[maxn];
int n,q;
inline int lb(int x) {
return x & -x;
}
void add1(int x,ll v) {
for (; x <= n; x += lb(x))
c1[x] += v;
}
void add2(int x,ll v) {
for (; x <= n; x += lb(x))
c2[x] += v;
}
ll read(int x) {
ll tot = 0;
for (int i = x; i; i -= lb(i))
tot += x * c1[i] - c2[i];
return tot;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
while (cin >> n >> q) {
memset(c1, 0, sizeof(c1));
memset(c2, 0, sizeof(c2));
for (int i = 1; i <= n; i++) {
cin >> a[i];
add1(i, a[i] - a[i - 1]);
add2(i, (i - 1) * (a[i] - a[i - 1]));
}
for (int i = 1; i <= q; i++) {
char c;
cin >> c;
if (c == 'Q') {
int l, r;
cin >> l >> r;
cout << read(r) - read(l - 1) << endl;
} else {
int l, r, v;
cin >> l >> r >> v;
add1(l, v);
add1(r + 1, -v);
add2(l, (l - 1) * v);
add2(r + 1, r * (-v));
}
}
}
return 0;
}