【题意】:给出n(n<=100000)个数的初始值,编号1~n,再给出q(q<=100000)个操作,不定时往第i个数到第j个数上加上一个常数c或者查询第i个数到第j个数的和。
【题解】:还是线段树的入门题目,凭自己的理解裸打了一次线段树,对延迟标记理解得更透切了。
注意要用long long.
【代码】:
1 #include "iostream"
2 #include "cstdio"
3 #include "cstring"
4 #include "algorithm"
5 #include "vector"
6 #include "queue"
7 using namespace std;
8 #define pb push_back
9 #define lc(x) (x << 1)
10 #define rc(x) (x << 1 | 1)
11 #define lowbit(x) (x & (-x))
12 #define MAX 100050
13 #define ll long long
14 ll lazy[MAX<<2], sum[MAX<<2];
15 int n, q;
16
17 void pushup(int p) {
18 sum[p] = sum[lc(p)] + sum[rc(p)];
19 }
20
21 void pushdown(int p, int len) {
22 if(lazy[p]) {
23 lazy[lc(p)] += lazy[p];
24 lazy[rc(p)] += lazy[p];
25 sum[lc(p)] += (len - (len >> 1)) * lazy[p];
26 sum[rc(p)] += (len >> 1) * lazy[p];
27 lazy[p] = 0;
28 }
29 }
30
31 void build(int l, int r, int p) {
32 lazy[p] = 0;
33 if(l == r) {
34 scanf("%lld", &sum[p]);
35 return;
36 }
37 int mid = (l + r) >> 1;
38 build(l, mid, lc(p));
39 build(mid + 1, r, rc(p));
40 pushup(p);
41 }
42
43 void update(int L, int R, ll c, int l, int r, int p) {
44 if(L <= l && r <= R) {
45 lazy[p] += c;
46 sum[p] += c * (r - l + 1);
47 return;
48 }
49 pushdown(p, r - l + 1);
50 int mid = (l + r) >> 1;
51 if(L <= mid) update(L, R, c, l, mid, lc(p));
52 if(R > mid) update(L, R, c, mid + 1, r, rc(p));
53 pushup(p);
54 }
55
56 ll query(int L, int R, int l, int r, int p) {
57 ll res = 0;
58 if(L <= l && r <= R) {
59 return sum[p];
60 }
61 pushdown(p, r - l + 1);
62 int mid = (l + r) >> 1;
63 if(L <= mid) res += query(L, R, l, mid, lc(p));
64 if(R > mid) res += query(L, R, mid + 1, r, rc(p));
65 pushup(p);
66 return res;
67 }
68
69 int main() {
70 char str[5];
71 int a, b;
72 ll c;
73 while(~scanf("%d%d", &n, &q)) {
74 build(1, n, 1);
75 while(q--) {
76 scanf("%s%d%d", str, &a, &b);
77 if(str[0] == 'Q') printf("%lld\n", query(a, b, 1, n, 1));
78 else {
79 scanf("%lld", &c);
80 update(a, b, c, 1, n, 1);
81 }
82 }
83 }
84 return 0;
85 }