题目来源:http://poj.org/problem?id=3468
树状数组做法:https://blog.csdn.net/moon_sky1999/article/details/81284933
线段树区间修改、区间查询模板题。
代码:
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1E5+10;
int n,q;
struct tree {
int left, right;
long long sum, add;
}c[maxn<<2];
int a[maxn];
long long ans=0;
void build(int id,int l,int r) {
c[id].left = l;
c[id].right = r;
c[id].add = 0;
if (l == r)return;
int mid = (l + r) >> 1;
build(id << 1, l, mid);
build(id << 1 | 1, mid + 1, r);
c[id].sum = c[id << 1].sum + c[id << 1 | 1].sum;
}
void pushdown(int id) {
c[id << 1].sum += (c[id << 1].right - c[id << 1].left + 1) * c[id].add;
c[id << 1].add += c[id].add;
c[id << 1 | 1].sum += (c[id << 1 | 1].right - c[id << 1 | 1].left + 1) * c[id].add;
c[id << 1 | 1].add += c[id].add;
c[id].add = 0;
}
void query_sum(int id,int l,int r) {
if (r < c[id].left || l > c[id].right)return;
if (c[id].left >= l && c[id].right <= r) {
ans += c[id].sum;
return;
}
if (c[id].add)pushdown(id);
query_sum(id << 1, l, r);
query_sum(id << 1 | 1, l, r);
c[id].sum = c[id << 1].sum + c[id << 1 | 1].sum;
}
void update(int id,int l,int r,int v) {
if (c[id].left > r || c[id].right < l)return;
if (c[id].left >= l && c[id].right <= r) {
c[id].add += v;
c[id].sum += (c[id].right - c[id].left + 1) * v;
return;
}
if (c[id].add)pushdown(id);
update(id << 1, l, r, v);
update(id << 1 | 1, l, r, v);
c[id].sum = c[id << 1].sum + c[id << 1 | 1].sum;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
while (cin >> n >> q) {
for (int i = 1; i <= n; i++)cin >> a[i];
build(1, 1, n);
for (int i = 1; i <= n; i++)update(1, i, i, a[i]);
for (int i = 1; i <= q; i++) {
char c;
cin >> c;
if (c == 'Q') {
int l, r;
cin >> l >> r;
ans = 0;
query_sum(1, l, r);
cout << ans << endl;
} else {
int l, r, v;
cin >> l >> r >> v;
update(1, l, r, v);
}
}
}
return 0;
}