POJ 3468 A Simple Problem with Integers(线段树:区间更新)

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 }
原文地址:https://www.cnblogs.com/zyb993963526/p/6561795.html