http://poj.org/problem?id=3468
题意:
给出一串数,每次在一个区间内增加c,查询[a,b]时输出a、b之间的总和。
思路:
总结一下懒惰标记的用法吧。
比如要对一个区间范围内的数都要加c,在找到这个区间之后,本来它的孩子结点也是需要更新的,但是我们可以暂时不更新,如果到时候需要用到这些孩子结点的时候,我们再来更新。这个时候就要用到懒惰标记了,也就是add[o]=c,之后它的孩子结点更新时就只需要加上add[o]就可以了。
1 #include<iostream> 2 #include<string> 3 #include<cstring> 4 #include<cstdio> 5 using namespace std; 6 7 const int maxn = 100000 + 10; 8 int n, m; 9 10 long long add[maxn << 2]; 11 long long sum[maxn << 2]; 12 13 void PushDown(int o, int m) 14 { 15 if (add[o]) 16 { 17 //传递懒惰标记 18 add[o << 1] += add[o]; 19 add[o << 1 | 1] += add[o]; 20 //更新子节点的值 21 sum[o << 1] += add[o] * (m - (m >> 1)); 22 sum[o << 1 | 1] += add[o] * (m >> 1); 23 //出去懒惰标记 24 add[o] = 0; 25 } 26 } 27 28 void PushUp(int o) 29 { 30 sum[o] = sum[o << 1] + sum[o << 1 | 1]; 31 } 32 33 void build(int L, int R, int o) 34 { 35 add[o] = 0; 36 if (L == R) 37 { 38 scanf("%lld", &sum[o]); 39 return; 40 } 41 int mid = (L + R) / 2; 42 build(L, mid, 2 * o); 43 build(mid + 1, R, 2 * o + 1); 44 PushUp(o); 45 } 46 47 void update(int L, int R, int x, int l,int r,int o) 48 { 49 if (L <= l && R >= r) //如果找到区间了,则不需要往下更新孩子结点了,等下次需要时再更新 50 { 51 add[o] += x; 52 sum[o] += (r - l + 1)*x; 53 return; 54 } 55 PushDown(o, r - l + 1); 56 int mid = (l + r) / 2; 57 if (L <= mid) 58 update(L, R, x, l, mid, 2 * o); 59 if (R > mid) 60 update(L, R, x, mid + 1, r, 2 * o + 1); 61 PushUp(o); 62 } 63 64 long long query(int L, int R, int l, int r, int o) 65 { 66 if (L <= l && R >= r) 67 return sum[o]; 68 PushDown(o, r - l + 1); 69 int mid = (l + r) / 2; 70 long long ans = 0; 71 if (L <= mid) 72 ans += query(L, R, l, mid, 2 * o); 73 if (R > mid) 74 ans += query(L, R, mid + 1, r, 2 * o + 1); 75 return ans; 76 } 77 78 79 int main() 80 { 81 //freopen("D:\txt.txt", "r", stdin); 82 while (~scanf("%d%d", &n, &m)) 83 { 84 build(1, n, 1); 85 char c[5]; 86 int x, y, z; 87 while (m--) 88 { 89 scanf("%s", &c); 90 if (c[0] == 'Q') 91 { 92 scanf("%d%d", &x, &y); 93 printf("%lld ", query(x, y, 1, n, 1)); 94 } 95 else 96 { 97 scanf("%d%d%d", &x, &y, &z); 98 update(x, y, z, 1, n, 1); 99 } 100 } 101 } 102 }