• 线段树模板(一)单点更新,区间查询


    关于线段树的原理在此不赘述,可参考:https://www.cnblogs.com/AC-King/p/7789013.html

    此处用结构体的线段树

    一、建树模板:

    #define MID(l, r) ((l) + ((r) - (l)) / 2)
    #define lson(o) ((o)<<1)
    #define rson(o) ((o)<<1|1)
    1
    int a[maxn]; 2 struct node 3 { 4 int l, r, mmax, mmin, sum; 5 }tree[maxn]; 6 void build(int o, int l, int r) 7 { 8 tree[o].l = l, tree[o].r = r; 9 if(l == r) 10 { 11 tree[o].mmax = tree[o].mmin = tree[o].sum = a[l]; 12 return; 13 } 14 int m = MID(l, r); 15 int lc = lson(o), rc = rson(o); 16 build(lc, l, m); 17 build(rc, m + 1, r); 18 tree[o].mmax = max(tree[lc].mmax, tree[rc].mmax); 19 tree[o].mmin = min(tree[lc].mmin, tree[rc].mmin); 20 tree[o].sum = tree[lc].sum + tree[rc].sum; 21 }

    二、查询区间[ql, qr]中的max,min,sum

     1 int ql, qr;//查询区间[ql, qr]中的max,min,sum
     2 int ans_max, ans_min, ans_sum;
     3 void query_init()//查询前,将全局变量初始化
     4 {
     5     ans_max = -INF;
     6     ans_min = INF;
     7     ans_sum = 0;
     8 }
     9 void query(int o)
    10 {
    11     if(ql <= tree[o].l && qr >= tree[o].r)//[L, R]包含在[ql, qr]区间内,直接用该节点的信息,达到线段树查询快的操作
    12     {
    13         ans_max = max(ans_max, tree[o].mmax);
    14         ans_min = min(ans_min, tree[o].mmin);
    15         ans_sum += tree[o].sum;
    16         return;
    17     }
    18     int m = MID(tree[o].l, tree[o].r);
    19     if(ql <= m)query(lson(o));
    20     if(qr > m)query(rson(o));
    21 }

    三、单点更新,a[p] += v

    如果需要更新成a[p]  = v,把下面的+=换成=即可

     1 //单点更新,a[p] += v;
     2 int p, v;
     3 void update(int o)
     4 {
     5     if(tree[o].l == tree[o].r)
     6     {
     7         tree[o].mmax += v;
     8         tree[o].mmin += v;
     9         tree[o].sum += v;
    10         return;
    11     }
    12     int m = MID(tree[o].l, tree[o].r);
    13     int lc = lson(o), rc = rson(o);
    14     if(p <= m)update(lc);
    15     else update(rc);
    16     tree[o].mmax = max(tree[lc].mmax, tree[rc].mmax);
    17     tree[o].mmin = min(tree[lc].mmin, tree[rc].mmin);
    18     tree[o].sum = tree[lc].sum + tree[rc].sum;
    19 }

    四、综上所述

    注意开4倍区间

    #define MID(l, r) ((l) + ((r) - (l)) / 2)
    #define lson(o) ((o)<<1)
    #define rson(o) ((o)<<1|1)
    1
    int a[maxn]; 2 struct node 3 { 4 int l, r, mmax, mmin, sum; 5 }tree[maxn]; 6 void build(int o, int l, int r) 7 { 8 tree[o].l = l, tree[o].r = r; 9 if(l == r) 10 { 11 tree[o].mmax = tree[o].mmin = tree[o].sum = a[l]; 12 return; 13 } 14 int m = MID(l, r); 15 int lc = lson(o), rc = rson(o); 16 build(lc, l, m); 17 build(rc, m + 1, r); 18 tree[o].mmax = max(tree[lc].mmax, tree[rc].mmax); 19 tree[o].mmin = min(tree[lc].mmin, tree[rc].mmin); 20 tree[o].sum = tree[lc].sum + tree[rc].sum; 21 } 22 int ql, qr;//查询区间[ql, qr]中的max,min,sum 23 int ans_max, ans_min, ans_sum; 24 void query_init()//查询前,将全局变量初始化 25 { 26 ans_max = -INF; 27 ans_min = INF; 28 ans_sum = 0; 29 } 30 void query(int o) 31 { 32 if(ql <= tree[o].l && qr >= tree[o].r)//[L, R]包含在[ql, qr]区间内,直接用该节点的信息,达到线段树查询快的操作 33 { 34 ans_max = max(ans_max, tree[o].mmax); 35 ans_min = min(ans_min, tree[o].mmin); 36 ans_sum += tree[o].sum; 37 return; 38 } 39 int m = MID(tree[o].l, tree[o].r); 40 if(ql <= m)query(lson(o)); 41 if(qr > m)query(rson(o)); 42 } 43 //单点更新,a[p] += v; 44 int p, v; 45 void update(int o) 46 { 47 if(tree[o].l == tree[o].r) 48 { 49 tree[o].mmax += v; 50 tree[o].mmin += v; 51 tree[o].sum += v; 52 return; 53 } 54 int m = MID(tree[o].l, tree[o].r); 55 int lc = lson(o), rc = rson(o); 56 if(p <= m)update(lc); 57 else update(rc); 58 tree[o].mmax = max(tree[lc].mmax, tree[rc].mmax); 59 tree[o].mmin = min(tree[lc].mmin, tree[rc].mmin); 60 tree[o].sum = tree[lc].sum + tree[rc].sum; 61 }
  • 相关阅读:
    C++ 虚成员函数和动态联编
    C++ 多态公有继承
    C++ 继承特性
    C++ 公有派生
    C++ 基类与派生类
    C++ 类继承
    C++ 伪私有方法
    C++ new失败
    mysql用户授权
    linux时间设置
  • 原文地址:https://www.cnblogs.com/fzl194/p/9024340.html
Copyright © 2020-2023  润新知