c++ - 树中路径的范围查询

标签 c++ algorithm path tree segment-tree

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

给你一个有 N ( <=10^5) 个节点的有根树。最初所有节点的值为 0。将对树进行 M 次更新 (<=10^5),其形式为

Add x y – 将 y 添加到节点 x 。

AddUp x y – 将 y 添加到 x,x 的父级,x 的父级的父级,直到根。

之后会有 Q 个查询(<=10^5)个查询,您将被要求提供节点的值或以该节点为根的子树的总和。

我做了什么:-

首先我尝试了根据操作更新每个节点的朴素算法,但显然这很花时间。

我也想过使用线段树和延迟传播,但想不出合适的方法。

感谢任何帮助,谢谢!

最佳答案

首先,构建一个图表,其中 child 指向他们的 parent 。 之后,解析所有更新并将 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的值是V.sum_add + V.sum_add_up,查询V的子树就是V.subtree_sum.

关于c++ - 树中路径的范围查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46915778/

相关文章:

c++ - ZMQ C++ 从特定工作人员发送和接收

c++ - 异常规范或多或少的限制

java - Thread.sleep 在循环中调用 - 在这种情况下如何防止它(通过重构)?

string - 当目标是找到特定字符串的所有出现时,KMP 的最坏情况复杂度是多少?

python - 操作系统错误 : The CUDA lib64 path could not be located in/usr/lib64

vb6 - 外部 DLL 应该放在哪里?

c++ - 模板参数的引用变量的问题

c++ - 从哪里获得用于 C++ 序列化的神话般的 Microsoft msgtool

algorithm - 它是共享数据的安全机制吗?

PHP 从 url 获取版本