【问题标题】:Iterative segment tree implmentation迭代段树实现
【发布时间】:2020-07-22 17:31:27
【问题描述】:

我指的是这篇文章: https://www.geeksforgeeks.org/segment-tree-efficient-implementation/

在此处粘贴代码以供参考。我的问题在代码下方。

#include <bits/stdc++.h> 
using namespace std; 

// limit for array size 
const int N = 100000; 

int n; // array size 

// Max size of tree 
int tree[2 * N]; 

// function to build the tree 
void build( int arr[]) 
{ 
    // insert leaf nodes in tree 
    for (int i=0; i<n; i++)  
        tree[n+i] = arr[i]; 

    // build the tree by calculating parents 
    for (int i = n - 1; i > 0; --i)  
        tree[i] = tree[i<<1] + tree[i<<1 | 1];   
} 

// function to update a tree node 
void updateTreeNode(int p, int value) 
{ 
    // set value at position p 
    tree[p+n] = value;              // {Question} Why is this assigned before updating the parent index to access?
    p = p+n;

    // move upward and update parents 
    for (int i=p; i > 1; i >>= 1) 
        tree[i>>1] = tree[i] + tree[i^1]; 
} 

// function to get sum on interval [l, r) 
int query(int l, int r) 
{ 
    int res = 0; 

    // loop to find the sum in the range 
    for (l += n, r += n; l < r; l >>= 1, r >>= 1) 
    { 
        if (l&1) 
            res += tree[l++]; 

        if (r&1) 
            res += tree[--r];
        // {Question} What happens if !(l&1) or !(r&1) ? res is not accumulated anywhere. Isn't this wrong?
    } 


    return res; 
} 

// driver program to test the above function 
int main() 
{ 
    int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; 

    // n is global 
    n = sizeof(a)/sizeof(a[0]); 

    // build tree 
    build(a); 

    // print the sum in range(1,2) index-based 
    cout << query(1, 3)<<endl; 

    // modify element at 2nd index 
    updateTreeNode(2, 1); 

    // print the sum in range(1,2) index-based 
    cout << query(1, 3)<<endl; 

    return 0; 
}

问题:

  1. updateTreeNode 内,其中值被设置为父级, 为什么在分配树中的值之后,父级会增加数组大小? 不应该是以前吗? 这篇文章的原始代码行是这样实现的: for (tree[parent += n] = value; parent &gt; 1; parent &gt;&gt;= 1) 其中parent=parent+n 首先执行。 有人能帮我理解为什么这段代码还能正常运行吗?

  2. query 内返回区间 [l, r) 中的和,这段代码似乎添加了 结果仅适用于 l 的奇数值。 然而,我看到结果正确地返回了偶值区间的总和。

    由于没有else &lt;accumulate result&gt;,结果应该是跳过累积偶数间隔,对吧?我错过了什么?

【问题讨论】:

    标签: c++ algorithm data-structures tree segment-tree


    【解决方案1】:

    问题 1

    变量p 不代表父级,它代表子级。在for循环中,i是子节点,我们更新i的父节点的值。

    tree[p+n] = value;:更新离开节点(没有孩子的节点)的值。然后我们从离开节点更新节点父节点的值。 tree[i&gt;&gt;1] = tree[i] + tree[i^1];, tree[i&gt;&gt;1]tree[i]' 父级。

    例如:数组大小为16(树大小为32),我想更新arr[8]。所以我打电话给updateTreeNode(8, value)。首先更新three[8+16],对应arr[8]。然后将p 设置为 24。在 for 循环中,我们更新 p 的父级 (tree[12]),然后将 p 设置为 p/2 (p=12),直到 p 没有父级。

    问题 2

    如果lr 是偶数,我们在下一次重复中添加父级的值。这就是段树的作用,避免查询区间中的每个元素。

    例如:数组大小为16,我要查询[8,10)。在分段树中,区间为 [24,26)。我们不需要添加tree[24]tree[25]的值,我们添加tree[12]的值!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-09
      • 2011-08-17
      • 2011-06-02
      • 2012-07-11
      • 2014-07-22
      • 2013-11-02
      相关资源
      最近更新 更多