码迷,mamicode.com
首页 > 其他好文 > 详细

线段树

时间:2021-04-06 15:08:05      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:初始化   --   modify   一段   class   初始   mat   math   存在   

主要有两个操作:push_up 与 push_down.

push_up

用子节点来算父节点信息,如:sum = l.sum + r.sum

push_down

父节点的修改信息下传到子节点

基本操作

  1. push_up(u)
  2. bulid() 将一段区间初始化为线段树
  3. modify 修改 \(\left \{ \begin{array}{} 单点&\ easy \\ 区间&\ push\_up \ hard \ 懒标记 \end{array} \right.\)
  4. query
  5. push_down

示意:

                       --------------------[1,10]---------------------------
		         /                                              \                 
                 ------[1,5]-------                             --------[6,10]-------
                /                  \                            /                 \ 
           ---[1,3]---         --[4,5]--                   ---[6,8]---        --[9,10]--
            /      \             /   \                     /         \           /          --[1,2]--   -3-         -4-   -5-              --[6,7]--      -8-       -9-  -10-
          /  \                                          /           -1-  -2-                                      -6-   -7-

\(mid=[\frac{l+r}{2}]\)

\([l,mid]\ [r,mid]\)

满二叉树 \(\Longrightarrow\) 用一维数组来存整个数.

编号是x \(\left \{ \begin{array}{} 父节点\ &\frac{x}{2} \ &x\gg 1 \\ 左儿子\ &2x\ &x\ll1 \\ 右儿子\ &2x+1\ &x\ll1|1 \end{array} \right.\)

线段树开空间开4n

bulid

build(int u, int l, int r) {
    tr[u].l = l, tr[u].r = r;
    if (l == r) return;
    int mid = l + r >> 1;
    build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
    push_up(u);
}

query

\([l,R]\): 当前查询的区间.

\([T_L,T_R]\): 树中节点的范围.

证明复杂度为 O(logN):

  1. \([T_L;T_R]\subset [L,R]\) 直接返回.

  2. \([L,R]\land[T_L,T_R]\ne\varnothing\)

    • TL|----mid----|TR
           L|------------|R
          TL <= L <= TR <= R
      

      \(\left \{ \begin{array}{} l>mid \ 只递归右边 \\ l \leq mid \left \{ \begin{array}{} 递归左边\\ 递归右边 \end{array} \right.\end{array} \right.\)

      看似是递归两边,其实右边再递归到下一层就返回了.

    •     TL|----mid----|TR
      L|-----------|R
      

      与上面对称

    •  TL|--------mid--------|TR
             L|---------|R
      

      \(\left \{ \begin{array}{} R \le mid \ 递归左\\ L>mid\ 递归右\\ 其他\ 递归两边\end{array} \right.\)

    • 递归两边只会发生一次,因为一旦分裂,就会变成情况1.

  3. \([L,R]\land[T_L,T_R]=\varnothing\) 不存在

线段树

标签:初始化   --   modify   一段   class   初始   mat   math   存在   

原文地址:https://www.cnblogs.com/phr2000/p/14617635.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!