题目大意:
一个序列,n个数字
两个操作,C x y z 表示 x 到 y 区间内的数字都加 z
Q x y 表示查询 x 到 y 的区间和
线段树模板题,注意数据范围就好了,sum 和 标记都用long long基本就可以了
#include <iostream>
#include <cstdio>
#include <cstring>
#define mem(a, b) memset(a, b, sizeof a)
#pragma warning (disable:4996)
#pragma warning (disable:6031)
#pragma warning (disable:26451)
#pragma warning (disable:4244)
using namespace std;
typedef long long ll;
const int N = 110000;
struct {
int l, r;
ll lazy;
ll sum;
}c[N * 4];
ll n, m;
void build(int l, int r, int k) {
c[k].l = l;
c[k].r = r;
if (l == r) {
scanf("%lld", &c[k].sum);
return;
}
int mid = (l + r) / 2;
build(l, mid, k * 2);
build(mid + 1, r, k * 2 + 1);
c[k].sum = c[k * 2].sum + c[k * 2 + 1].sum;
}
void down(int k) {
if (c[k].lazy) {
c[k * 2].sum += (c[k * 2].r - c[k * 2].l + 1) * c[k].lazy;
c[k * 2 + 1].sum += (c[k * 2 + 1].r - c[k * 2 + 1].l + 1) * c[k].lazy;
c[k * 2 + 1].lazy += c[k].lazy;
c[k * 2].lazy += c[k].lazy;
c[k].lazy = 0;
}
}
void update(int l, int r, int k, int d) {
if (l <= c[k].l && r >= c[k].r) {
c[k].sum += (c[k].r - c[k].l + 1) * d;
c[k].lazy += d;
return;
}
down(k);
int mid = (c[k].l + c[k].r) / 2;
if (l <= mid)update(l, r, k * 2, d);
if (r > mid)update(l, r, k * 2 + 1, d);
c[k].sum = c[k * 2].sum + c[k * 2 + 1].sum;
}
ll query(int l, int r, int k) {
if (l <= c[k].l && r >= c[k].r) {
return c[k].sum;
}
else if (l > c[k].r || r < c[k].l) {
return 0;
}
down(k);
return query(l, r, k * 2) + query(l, r, k * 2 + 1);
}
int main()
{
while (~scanf("%lld %lld", &n, &m)) {
mem(c, 0);
build(1, n, 1);
while (m--) {
char ch[5];
scanf("%s", ch);
if (ch[0] == 'Q') {
int x, y;
scanf("%d %d", &x, &y);
printf("%lld\n", query(x, y, 1));
}
else {
int x, y;
ll z;
scanf("%d %d %lld", &x, &y, &z);
update(x, y, 1, z);
}
}
}
return 0;
}