zoukankan      html  css  js  c++  java
  • 线段树区间修改模板

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

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

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

    模板一:
    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 }
    代码君
  • 相关阅读:
    QQ音乐 删除历史登录设备
    mweb发布文章为什么默认TinyMCE编辑器?
    Mac 安装 Homebrew
    uniapp配置scss支持
    PHPRedis教程之geo
    CentOS7通过YUM安装NGINX稳定版本
    CentOS7通过YUM安装MySQL5.6
    更换composer镜像源为阿里云
    使用chattr禁止文件被删除
    centos 7 源码安装 mysql 5.6
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4382515.html
Copyright © 2011-2022 走看看