zoukankan      html  css  js  c++  java
  • ZKW线段树学习记录 (1)

    zkw线段树讲稿:统计的力量

    1、区间求和

    其实zkw线段树的核心思想就是:用1表示根节点,那么每一个节点的值就表示以该节点编号为后缀的所有节点的和。

    4=100,其恰好包括了1000=8,1001=9的值。而在X<>2^n-1时,X+1即是其兄弟右节点,X<>2^n时,X-1即是其兄弟左节点。

    找第I个叶子节点(0<=i<n):

    记录线段树有k层,则叶子节点编号为2^(n-1)+t     O(1)

    区间和:

    Warning:理论上能放 [0,2^N) 的树 其实只能查询 [1,2^N - 2] 的范围

    先找到s=s-1,t=t+1的叶子节点,然后不断向上移,若s是左子树,则其右兄弟必在区间内,若t是右子树,左子树必在区间内。然后同时s、t上移一层,直至s、t为相邻的兄弟节点(s xor t=1)

    Func Query(s,t)  // 询问从s到t闭区间
    s = s – 1, t = t + 1;  // 变为开区间
    s += M, t += M;  // 找到叶子位置 M=2^(层数-1)
    While not ((s xor t) == 1) do //若s与t不相邻
    If ((s and 1) == 0) Answer += Tree[s + 1]; //若s是左子树,加上右兄弟
    If ((t and 1) == 1) Answer += Tree[t – 1]; //若t是右子树,加上左兄弟
    s = s >> 1, t = t >> 1; //上移一层
    

    因为区间和头尾无法求,所以一般多建一层会保险一点,题目中要[0,1023],直接建一个[0,2047]的树就行了。

    2、修改

    基本和线段树相同,只不过可以直接找到叶子节点。

    Func Change(n,NewValue)
    n += M; //找到叶子节点编号
    Tree[n] = NewValue;
    While n > 1 do
    n = n >> 1;
    Tree[n]  = Tree[2n] + Tree[2n+1];//递归赋值
    
  • 相关阅读:
    嵌入式驱动视频2019.03.24
    wps如何输入连续的长破折号
    python绘图问题
    2.13
    2.12
    2.10
    2.9
    2.8
    2.7
    2.5
  • 原文地址:https://www.cnblogs.com/htfy/p/2851694.html
Copyright © 2011-2022 走看看