Description
给定一个长度为N的数列A,以及M条指令,每条指令可能是以下两种之一:
1、“C l r d”,表示把 A[l],A[l+1],…,A[r] 都加上 d。
2、“Q l r”,表示询问 数列中第 l~r 个数的和。
对于每个询问,输出一个整数表示答案。
Input
第一行两个整数N,M。
第二行N个整数A[i]。
接下来M行表示M条指令,每条指令的格式如题目描述所示。
数据范围
1≤N,M≤10^5,
|d|≤10000,
|A[i]|≤1000000000
Output
对于每个询问,输出一个整数表示答案。
每个答案占一行。
Sample Input
10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4
Sample Output
4
55
9
15
模板题还是需要闭着眼多敲几遍
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
using ll = long long;
const int SIZE = 100010;
struct SegmentTree
{
int l, r;
ll sum, add;
} tree[SIZE << 2];
int a[SIZE], n, m;
void build(int p, int l, int r)
{
tree[p].l = l, tree[p].r = r;
if (l == r)
{
tree[p].sum = a[l];
return;
}
int mid = (l + r) >> 1;
build(p << 1, l, mid);
build(p << 1 | 1, mid + 1, r);
tree[p].sum = tree[p<<1].sum + tree[p<<1|1].sum;
}
void spread(int p)
{
if (tree[p].add)
{
tree[p<<1].sum += tree[p].add * (tree[p<<1].r - tree[p<<1].l + 1);
tree[p<<1|1].sum += tree[p].add * (tree[p<<1|1].r - tree[p<<1|1].l + 1);
tree[p<<1].add += tree[p].add;
tree[p<<1|1].add += tree[p].add;
tree[p].add = 0;
}
}
void change(int p, int l, int r, int z)
{
if (l <= tree[p].l && r >= tree[p].r)
{
tree[p].sum += (ll)z * (tree[p].r - tree[p].l + 1);
tree[p].add += z;
return;
}
spread(p);
int mid = (tree[p].l + tree[p].r) >> 1;
if (l <= mid)
change(p << 1, l, r, z);
if (r > mid)
change(p << 1 | 1, l, r, z);
tree[p].sum = tree[p<<1].sum + tree[p<<1|1].sum;
}
ll ask(int p, int l, int r)
{
if (l <= tree[p].l && r >= tree[p].r)
return tree[p].sum;
spread(p);
int mid = (tree[p].l + tree[p].r) >> 1;
ll ans = 0;
if (l <= mid)
ans += ask(p << 1, l, r);
if (r > mid)
ans += ask(p << 1 | 1, l, r);
return ans;
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
build(1, 1, n);
while (m--)
{
char op[2];
int x, y, z;
scanf("%s%d%d", op, &x, &y);
if (op[0] == 'C')
{
scanf("%d", &z);
change(1, x, y, z);
}
else
printf("%lld\n", ask(1, x, y));
}
return 0;
}