Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 树中路径上的范围查询_C++_Algorithm_Path_Tree_Segment Tree - Fatal编程技术网

C++ 树中路径上的范围查询

C++ 树中路径上的范围查询,c++,algorithm,path,tree,segment-tree,C++,Algorithm,Path,Tree,Segment Tree,我在一次竞赛中遇到了这个问题(现在已经结束了),我想不出一个省时的算法 给您一个N(的根树,首先,构建一个图,其中子对象指向其父对象。 之后,解析所有更新并在树的每个节点中分别存储Add和AddUp的总和。 您的节点应具有以下变量: sum_add : the sum of all the Add of this node sum_add_up : the sum of all the AddUp of this node subtree_sum : the sum of the subtree

我在一次竞赛中遇到了这个问题(现在已经结束了),我想不出一个省时的算法


给您一个N(的根树,首先,构建一个图,其中子对象指向其父对象。 之后,解析所有更新并在树的每个节点中分别存储Add和AddUp的总和。 您的节点应具有以下变量:

sum_add : the sum of all the Add of this node
sum_add_up : the sum of all the AddUp of this node
subtree_sum : the sum of the subtree. Initialize with 0 by now.
现在,使用拓扑顺序横切图形,也就是说,如果节点的所有子节点都已处理,则只处理节点,这需要O(N)。现在让我定义处理函数

process(V) {
    V.sum_add_up = V.sum_add_up + sum(sum_add_up of all V.children)
    V.subtree_sum = V.sum_add + V.sum_add_up + sum(subtree_sum of all V.children)
}

现在您可以回答O(1)中的所有查询。对节点值的查询是
V.sum\u add+V.sum\u add\u-up
,对
V
子树的查询就是
V.subtree\u sum

,我认为这个问题只是直接应用了二叉搜索树,它具有平均的案例成本(在n次随机操作之后)
O(1.39log(n))
用于插入和查询

您所要做的就是递归地添加新节点,同时更新值和总和

实现也相当简单(很抱歉C#),例如
Add()
AddUp()
类似-每次转到左或右子树时增加值):

对于100万个数字:

Added(up) 1000000 values in: 3127 ms, 12211606 ticks
Got 1000000 values in:       1244 ms, 4857733 ticks

这是否足够有效?您可以尝试完整的代码。

这是一个Fenwick树,要解决此类问题,您必须对树执行拓扑排序,并计算每个节点的子节点数

      0
    /   \
   1     2
  / \
 3   4
索引:[0 1,2,3,4] 儿童:[4,2,0,0,0] 使用Topology,您将获得此向量0 1 3 4 2您需要将其反转:

fenwick Pos:  [0,1,2,3,4]
vector values:[2,4,3,1,0]
pos: [5,3,0,2,1]
使用fenwick树,您可以执行两种查询:更新查询、范围和查询 如果只需要更新索引调用
update(pos[index],y)
,则必须减少所有下一个值,
update(pos[index]+1,-y)
当您需要更新所有家长时,请调用
update(pos[index],y)
update(pos[index]+childrens[index]+1,-y);


要知道一个职位的价值,你需要调用pos[索引]上的范围和查询。

如果你想让它更正式,或者如果你需要我证明它的时间复杂性,请告诉我。嗨,Gabriel,我将介绍你的解决方案并试着理解它。非常感谢你的帮助!!你能给我问题的链接吗?
      0
    /   \
   1     2
  / \
 3   4
fenwick Pos:  [0,1,2,3,4]
vector values:[2,4,3,1,0]
pos: [5,3,0,2,1]