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

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <assert.h>
     6 using namespace std;
     7 const int maxn = 100000+ 10;
     8 
     9 //update_add:把A[L]~A[R]的值全部加v_add
    10 //update_set:把A[l]~A[R]的值设为v_set
    11 //query:计算子序列的元素和,最小值,最大值
    12 
    13 int sumv[2*maxn],minv[2*maxn],maxv[2*maxn];
    14 int addv[2*maxn], setv[2*maxn];
    15 int y1, y2, v_add, v_set;
    16 
    17 void maintain(int o, int L, int R) {
    18     int lc = 2*o, rc = 2*o + 1;
    19     sumv[o] = minv[o] = maxv[o] = 0;
    20     if(setv[o] >= 0) {
    21         sumv[o] = setv[o] * (R-L+1);
    22         minv[o] = maxv[o] = setv[o];
    23     }
    24     else if(R > L) {
    25         sumv[o] = sumv[lc] + sumv[rc];
    26         minv[o] = min(minv[lc], minv[rc]);
    27         maxv[o] = max(maxv[lc], maxv[rc]);
    28     }
    29     minv[o] += addv[o]; maxv[o] += addv[o]; sumv[o] += addv[o] * (R-L+1);
    30 }
    31 void pushdown(int o) {
    32     int lc = 2*o, rc = 2*o+1;
    33     if(setv[o] >= 0) {
    34         setv[lc] = setv[rc] = setv[o];
    35         addv[lc] = addv[rc] = 0;
    36         setv[o] = -1;
    37     }
    38     if(addv[o] > 0) {
    39         addv[lc] += addv[o];
    40         addv[rc] += addv[o];
    41         addv[o] = 0;
    42     }
    43 }
    44 void update_add(int o, int L, int R) {
    45     int lc = 2*o, rc = o*2+1;
    46     if(y1 <= L && y2 >= R) {
    47         addv[o] += v_add;
    48     }
    49     else {
    50         pushdown(o);
    51         int M = L + (R-L)/2;
    52         if(y1 <= M) update_add(lc, L, M); else maintain(lc, L, M);
    53         if(y2 > M) update_add(rc, M+1, R);else maintain(rc, M+1, R);
    54     }
    55     maintain(o, L, R);
    56 }
    57 void update_set(int o, int L, int R) {
    58     int lc = 2*o, rc = o*2+1;
    59     if(y1 <= L && y2 >= R) {
    60         setv[o] = v_set;
    61         addv[o] = 0;
    62     }
    63     else {
    64         pushdown(o);
    65         int M = L + (R-L)/2;
    66         if(y1 <= M) update_set(lc, L, M); else maintain(lc, L, M);
    67         if(y2 > M) update_set(rc, M+1, R); else maintain(rc, M+1, R);
    68     }
    69     maintain(o, L, R);
    70 }
    71 int _min, _max, _sum;
    72 void query(int o, int L, int R, int add) {
    73     if(setv[o] >= 0) {
    74         _sum += (add+setv[o]+addv[o]) * (min(R, y2)-max(L, y1)+1);
    75         _min = min(_min, setv[o]+addv[o]+add);
    76         _max = max(_max, setv[o]+addv[o]+add);
    77     }
    78     else if(y1 <= L && y2 >= R) {
    79         _sum += sumv[o] + add * (R-L+1);
    80         _min = min(_min, minv[o]+add);
    81         _max = max(_max, maxv[o]+add);
    82     }
    83     else {
    84         int M = L + (R-L)/2;
    85         if(y1 <= M) query(o*2, L, M, add+addv[o]);
    86         if(y2 > M) query(o*2+1, M+1, R, add + addv[o]);
    87     }
    88 }
    89 void init() {
    90     memset(setv, -1, sizeof setv);
    91     memset(addv, 0, sizeof addv);
    92     memset(sumv, 0, sizeof sumv);
    93     memset(minv, 0, sizeof minv);
    94     memset(maxv, 0, sizeof maxv);
    95 }

    以上代码思路详见白书即(刘汝佳《算法竞赛经典训练指南》)第三章线段树部分,需要注意的是:

      1.set操作时需要将该结点add标识清除

      2.pushdown操作以及maintain操作的位置

      3.其他方面的问题详见代码

  • 相关阅读:
    C++解决单纯形表
    VS2010 MFC Excel(3)
    VS2010 MFC Excel(1)
    VS2010 MFC 读取Excel(2)
    读取数量不定的输入数据
    牛顿插值
    连接数据库
    雅克比迭代
    NOIP模拟 24
    NOIP模拟 23
  • 原文地址:https://www.cnblogs.com/Kiraa/p/6046208.html
Copyright © 2011-2022 走看看