zoukankan      html  css  js  c++  java
  • 线段树模板 (刘汝佳)

    一、线段树(点修改

    Update(x,v):  把Ax修改为v

    Query(L,R): 计算区间[qL,qR] 最小值。

    代码:

    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. // Dynamic RMQ  
    2. // Rujia Liu  
    3. // 输入格式:  
    4. // n m    数组范围是a[1]~a[n],初始化为0。操作有m个  
    5. // 1 p v  表示设a[p]=v  
    6. // 2 L R  查询a[L]~a[R]的min  
    7. #include<cstdio>  
    8. #include<cstring>  
    9. #include<algorithm>  
    10. using namespace std;  
    11.   
    12. const int INF = 1000000000;  
    13. const int maxnode = 1<<17;  
    14.   
    15. int op, qL, qR, p, v;  //qL和qR为全局变量,询问区间[qL,qR];  
    16.   
    17. struct IntervalTree {  
    18.   int minv[maxnode];  
    19.   
    20.   void update(int o, int L, int R) {  
    21.     int M = L + (R-L)/2;  
    22.     if(L == R) minv[o] = v; // 叶结点,直接更新minv  
    23.     else {  
    24.       // 先递归更新左子树或右子树  
    25.       if(p <= M) update(o*2, L, M); else update(o*2+1, M+1, R);  
    26.       // 然后计算本结点的minv  
    27.       minv[o] = min(minv[o*2], minv[o*2+1]);  
    28.     }  
    29.   }  
    30.   
    31.   int query(int o, int L, int R) {  
    32.     int M = L + (R-L)/2, ans = INF;  
    33.     if(qL <= L && R <= qR) return minv[o]; // 当前结点完全包含在查询区间内  
    34.     if(qL <= M) ans = min(ans, query(o*2, L, M)); // 往左走  
    35.     if(M < qR) ans = min(ans, query(o*2+1, M+1, R)); // 往右走  
    36.     return ans;  
    37.   }  
    38. };  
    39.   
    40.   
    41. IntervalTree tree;  
    42.   
    43. int main() {  
    44.   int n, m;  
    45.   while(scanf("%d%d", &n, &m) == 2) {  
    46.     memset(&tree, 0, sizeof(tree));  
    47.     while(m--) {  
    48.       scanf("%d", &op);  
    49.       if(op == 1) {  
    50.         scanf("%d%d", &p, &v);  
    51.         tree.update(1, 1, n);  // 修改树节点,或者是建树的过程  
    52.       } else {  
    53.         scanf("%d%d", &qL, &qR);  //修改询问区间  
    54.         printf("%d ", tree.query(1, 1, n));  
    55.       }  
    56.     }  
    57.   }  
    58.   return 0;  
    59. }  



    二、区间修改:

    1.操作一:

    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. // Fast Sequence Operations I  
    2. // Rujia Liu  
    3. // 输入格式:  
    4. // n m     数组范围是a[1]~a[n],初始化为0。操作有m个  
    5. // 1 L R v 表示设a[L]+=v, a[L+1]+v, ..., a[R]+=v  
    6. // 2 L R   查询a[L]~a[R]的sum, min和max  
    7. #include<cstdio>  
    8. #include<cstring>  
    9. #include<algorithm>  
    10. using namespace std;  
    11.   
    12. const int maxnode = 1<<17;  
    13.   
    14. int <span style="color:#ff0000;">_sum</span>, _min, _max, op, qL, qR, v; //<span style="color:#ff0000;">_sum为全局变量</span>  
    15.   
    16. struct IntervalTree {  
    17.   int sumv[maxnode], minv[maxnode], maxv[maxnode], addv[maxnode];  
    18.   
    19.   // 维护信息  
    20.   void maintain(int o, int L, int R) {  
    21.     int lc = o*2, rc = o*2+1;  
    22.     sumv[o] = minv[o] = maxv[o] = 0;  
    23.     if(R > L) {  
    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.     int lc = o*2, rc = o*2+1;  
    33.     if(qL <= L && qR >= R) { // 递归边界        
    34.       addv[o] += v; // 累加边界的add值  
    35.     } else {  
    36.       int M = L + (R-L)/2;  
    37.       if(qL <= M) update(lc, L, M);  
    38.       if(qR > M) update(rc, M+1, R);  
    39.     }  
    40.     maintain(o, L, R); // 递归结束前重新计算本结点的附加信息  
    41.   }  
    42.   
    43.   void query(int o, int L, int R, int add) {  
    44.     if(qL <= L && qR >= R) { // 递归边界:用边界区间的附加信息更新答案  
    45.       _sum += sumv[o] + add * (R-L+1);  
    46.       _min = min(_min, minv[o] + add);  
    47.       _max = max(_max, maxv[o] + add);  
    48.     } else { // 递归统计,累加参数add  
    49.       int M = L + (R-L)/2;  
    50.       if(qL <= M) query(o*2, L, M, add + addv[o]);  
    51.       if(qR > M) query(o*2+1, M+1, R, add + addv[o]);  
    52.     }  
    53.   }  
    54. };  
    55.   
    56. const int INF = 1000000000;  
    57.   
    58. IntervalTree tree;  
    59.   
    60. int main() {  
    61.   int n, m;  
    62.   while(scanf("%d%d", &n, &m) == 2) {  
    63.     memset(&tree, 0, sizeof(tree));  
    64.     while(m--) {  
    65.       scanf("%d%d%d", &op, &qL, &qR);  
    66.       if(op == 1) {  
    67.         scanf("%d", &v);  
    68.         tree.update(1, 1, n);  
    69.       } else {  
    70.         _sum = 0; _min = INF; _max = -INF;  
    71.         tree.query(1, 1, n, 0);  
    72.         printf("%d %d %d ", _sum, _min, _max);  
    73.       }  
    74.     }  
    75.   }  
    76.   return 0;  
    77. }  



    2.操作二:

    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
      1. // Fast Sequence Operations II  
      2. // Rujia Liu  
      3. // 输入格式:  
      4. // n m     数组范围是a[1]~a[n],初始化为0。操作有m个  
      5. // 1 L R v 表示设a[L]=a[L+1]=...=a[R] = v。其中v > 0  
      6. // 2 L R  查询a[L]~a[R]的sum, min和max  
      7. #include<cstdio>  
      8. #include<cstring>  
      9. #include<algorithm>  
      10. using namespace std;  
      11.   
      12. const int maxnode = 1<<17;  
      13.   
      14. int _sum, _min, _max, op, qL, qR, v;  
      15.   
      16. struct IntervalTree {  
      17.   int sumv[maxnode], minv[maxnode], maxv[maxnode], setv[maxnode];  
      18.   
      19.   // 维护信息  
      20.   void maintain(int o, int L, int R) {  
      21.     int lc = o*2, rc = o*2+1;  
      22.     if(R > L) {  
      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] = setv[o] * (R-L+1); }  
      28.   }  
      29.   
      30.   // 标记传递  
      31.   void pushdown(int o) {  
      32.     int lc = o*2, rc = o*2+1;  
      33.     if(setv[o] >= 0) { //本结点有标记才传递。注意本题中set值非负,所以-1代表没有标记  
      34.       setv[lc] = setv[rc] = setv[o];  
      35.       setv[o] = -1; // 清除本结点标记  
      36.     }  
      37.   }  
      38.   
      39.   void update(int o, int L, int R) {  
      40.     int lc = o*2, rc = o*2+1;  
      41.     if(qL <= L && qR >= R) { // 标记修改  
      42.       setv[o] = v;  
      43.     } else {  
      44.       pushdown(o);  
      45.       int M = L + (R-L)/2;  
      46.       if(qL <= M) update(lc, L, M); else maintain(lc, L, M);  
      47.       if(qR > M) update(rc, M+1, R); else maintain(rc, M+1, R);  
      48.     }  
      49.     maintain(o, L, R);  
      50.   }  
      51.   
      52.   void query(int o, int L, int R) {  
      53.     if(setv[o] >= 0) { // 递归边界1:有set标记  
      54.       _sum += setv[o] * (min(R,qR)-max(L,qL)+1);  
      55.       _min = min(_min, setv[o]);  
      56.       _max = max(_max, setv[o]);  
      57.     } else if(qL <= L && qR >= R) { // 递归边界2:边界区间  
      58.       _sum += sumv[o]; // 此边界区间没有被任何set操作影响  
      59.       _min = min(_min, minv[o]);  
      60.       _max = max(_max, maxv[o]);  
      61.     } else { // 递归统计  
      62.       int M = L + (R-L)/2;  
      63.       if(qL <= M) query(o*2, L, M);  
      64.       if(qR > M) query(o*2+1, M+1, R);  
      65.     }  
      66.   }  
      67. };  
      68.   
      69. const int INF = 1000000000;  
      70.   
      71. IntervalTree tree;  
      72.   
      73. int main() {  
      74.   int n, m;  
      75.   while(scanf("%d%d", &n, &m) == 2) {  
      76.     memset(&tree, 0, sizeof(tree));  
      77.     memset(tree.setv, -1, sizeof(tree.setv));  
      78.     tree.setv[1] = 0;  
      79.     while(m--) {  
      80.       scanf("%d%d%d", &op, &qL, &qR);  
      81.       if(op == 1) {  
      82.         scanf("%d", &v);  
      83.         tree.update(1, 1, n);  
      84.       } else {  
      85.         _sum = 0; _min = INF; _max = -INF;  
      86.         tree.query(1, 1, n);  
      87.         printf("%d %d %d ", _sum, _min, _max);  
      88.       }  
      89.     }  
      90.   }  
      91.   return 0;  
      92. }  
  • 相关阅读:
    [转]Hamcrest使用方法实例
    Maven配置浅析
    Guava API
    awk排序作业
    [转]awk使用手册
    Vue源码探究-全局API
    vue 组件间传值
    在2018年如何优雅的开发一个typescript语言的npm包?
    PHP四种序列化方案
    从 0 到 1 再到 100, 搭建、编写、构建一个前端项目
  • 原文地址:https://www.cnblogs.com/xianbin7/p/4489655.html
Copyright © 2011-2022 走看看