• 线段树区间修改模板


    本来打算把大白书第三章一口气攻下来的,但是这个线段树也是卡了好久。

    不敢过题太快,怕自己走马观花到头来结果什么都不会。

    可也不能再拖了,在做题中也许有更多的体会。

    模板一:
    1 L R v 表示区间[L, R]所有元素都加上v
    2 L R   表示查询区间[L, R]的sum, min, max
    sumv[o]的定义为:如果只执行节点o及其子孙节点的中的add操作,节点o对应区间中所有数之和

     1 //线段树区间修改
     2 //1 L R v 表示区间[L, R]所有元素都加上v
     3 //2 L R   表示查询区间[L, R]的sum, min, max
     4 //sumv[o]的定义为:如果只执行节点o及其子孙节点的中的add操作,节点o对应区间中所有数之和
     5 #include <cstdio>
     6 #include <cstring>
     7 #include <algorithm>
     8 using namespace std;
     9 
    10 const int maxnode = 1 << 17;
    11 
    12 int _sum, _min, _max, op, qL, qR, v;
    13 
    14 struct IntervalTree
    15 {
    16     int sumv[maxnode], minv[maxnode], maxv[maxnode], addv[maxnode];
    17 
    18     //维护信息
    19     void maintain(int o, int L, int R)
    20     {
    21         int lc = o*2, rc = o*2+1;
    22         if(R > L)
    23         {
    24             sumv[o] = sumv[lc] + sumv[rc];
    25             minv[o] = min(minv[lc], minv[rc]);
    26             maxv[o] = max(maxv[lc], maxv[rc]);
    27         }
    28         if(addv[o]) { minv[o] += addv[o]; maxv[o] += addv[o]; sumv[o] += addv[o] * (R-L+1); }
    29     }
    30 
    31     void update(int o, int L, int R)
    32     {
    33         int lc = o*2, rc = o*2+1;
    34         if(qL <= L && R <= qR) addv[o] += v;
    35         else
    36         {
    37             int M = (L + R) / 2;
    38             if(qL <= M) update(lc, L, M);
    39             if(qR > M) update(rc, M+1, R);
    40         }
    41         maintain(o, L, R);
    42     }
    43 
    44     void query(int o, int L, int R, int add)
    45     {
    46         if(qL <= L && R <= qR)
    47         {
    48             _sum += sumv[o] + add * (R-L+1);
    49             _min = min(_min, minv[o] + add);
    50             _max = max(_max, maxv[o] + add);
    51         }
    52         else
    53         {
    54             int M = (L + R) / 2;
    55             if(qL <= M) query(o*2, L, M, add + addv[o]);
    56             if(qR > M) query(o*2+1, M+1, R, add + addv[o]);
    57         }
    58     }
    59 }tree;
    60 
    61 const int INF = 1000000000;
    62 
    63 int main()
    64 {
    65     int n, m;
    66     while(scanf("%d%d", &n, &m) == 2)
    67     {
    68         memset(&tree, 0, sizeof(tree));
    69         while(m--)
    70         {
    71             scanf("%d%d%d", &op, &qL, &qR);
    72             if(op == 1) { scanf("%d", &v); tree.update(1, 1, n); }
    73             else
    74             {
    75                 _sum = 0; _min = INF; _max = -INF;
    76                 tree.query(1, 1, n, 0);
    77                 printf("%d %d %d
    ", _sum, _min, _max);
    78             }
    79         }
    80     }
    81 
    82     return 0;
    83 }
    代码君

    模板二:

    线段树区间修改set
    1 L R v 表示将区间[L, R]全部赋值为v (v >= 0)
    2 L R   表示查询区间[L, R]的sum, min, max

      1 //线段树区间修改set
      2 // 1 L R v 表示将区间[L, R]全部赋值为v (v >= 0)
      3 // 2 L R   表示查询区间[L, R]的sum, min, max
      4 #include <cstdio>
      5 #include <cstring>
      6 #include <algorithm>
      7 using namespace std;
      8 
      9 const int maxnode = 1 << 17;
     10 
     11 int _sum, _min, _max, op, qL, qR, v;
     12 
     13 struct IntervalTree
     14 {
     15     int sumv[maxnode], minv[maxnode], maxv[maxnode], setv[maxnode];
     16 
     17     //维护信息
     18     void maintain(int o, int L, int R)
     19     {
     20         int lc = o*2, rc = o*2;
     21         if(R > L)
     22         {
     23             sumv[o] = sumv[lc] + sumv[rc];
     24             minv[o] = min(minv[lc], minv[rc]);
     25             maxv[o] = max(maxv[lc], maxv[rc]);
     26         }
     27         if(setv[o] >= 0) { minv[o] = maxv[o] = setv[o]; sumv[o] = (R-L+1) * setv[o]; }
     28     }
     29 
     30     //标记传递
     31     void pushdown(int o, int L, int R)
     32     {
     33         int lc = o*2, rc = o*2+1;
     34         if(setv[o] >= 0)//-1表示没有标记过节点
     35         {
     36             setv[lc] = setv[rc] = setv[o];
     37             setv[o] = -1;//清除本节点的标记
     38         }
     39     }
     40 
     41     void update(int o, int L, int R)
     42     {
     43         int lc = o*2, rc = o*2+1;
     44         if(qL <= L && R <= qR) setv[o] = v;
     45         else
     46         {
     47             pushdown(o, L, R);
     48             int M = (L + R) / 2;
     49             if(qL <= M) update(lc, L, M); else maintain(lc, L, M);
     50             if(qR > M) update(rc, M+1, R); else maintain(rc, M+1, R);
     51         }
     52         maintain(o, L, R);
     53     }
     54 
     55     void query(int o, int L, int R)
     56     {
     57         if(setv[o] >= 0)//递归边界1:有set标记
     58         {
     59             _sum += setv[o] * (min(R, qR) - max(L, qL) + 1);
     60             _min = min(_min, setv[o]);
     61             _max = max(_max, setv[o]);
     62         }
     63         else if(qL <= L && R <= qR)
     64         {//递归边界2:边界区间,此区间没有收到set影响
     65             _sum += sumv[o];
     66             _min = min(_min, minv[o]);
     67             _max = max(_max, maxv[o]);
     68         }
     69         else
     70         {//递归统计
     71             int M = (L + R) / 2;
     72             if(qL <= M) query(o*2, L, M);
     73             if(qR > M) query(o*2+1, M+1, R);
     74         }
     75     }
     76 }tree;
     77 
     78 const int INF = 1000000000;
     79 
     80 int main()
     81 {
     82     int n, m;
     83     while(scanf("%d%d", &n, &m) == 2)
     84     {
     85         memset(&tree, 0, sizeof(tree));
     86         memset(tree.setv, -1, sizeof(tree.setv));
     87         tree.setv[0] = 1;
     88         while(m--)
     89         {
     90             scanf("%d%d%d", &op, &qL, &qR);
     91             if(op == 1) { scanf("%d", &v); tree.update(1, 1, n); }
     92             else
     93             {
     94                 _sum = 0; _min = INF; _max = -INF;
     95                 tree.query(1, 1, n);
     96                 printf("%d %d %d
    ", _sum, _min, _max);
     97             }
     98         }
     99     }
    100 
    101     return 0;
    102 }
    代码君
  • 相关阅读:
    [CodeForces]Codeforces Round #429 (Div. 2) ABC(待补)
    About Me
    2018-06-14
    Codeforces Codeforces Round #484 (Div. 2) E. Billiard
    Codeforces Codeforces Round #484 (Div. 2) D. Shark
    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings
    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes
    Codeforces Avito Code Challenge 2018 D. Bookshelves
    Codeforces Round #485 (Div. 2) D. Fair
    Codeforces Round #485 (Div. 2) F. AND Graph
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4382515.html
Copyright © 2020-2023  润新知