【问题标题】:Building of segment tree段树的构建
【发布时间】:2016-05-26 21:32:40
【问题描述】:

给定一个包含 n 个元素的整数数组 A 和 m 个查询,每个查询都包含一个整数 x,我必须回答数组中小于 x 的元素数。 0

示例:

A[]={105,2,9,3,8,5,7,7}

查询

6

8

104

回答

3

5

7

解释:

对于 query1 元素是={2,3,5}

对于 query2 元素是={2,3,5,7,7}

对于 query3 元素是={2,9,3,8,5,7,7}

问题:

如何使用分段树来解决这个问题?(我已经构建了分段树以在一个范围内查找最大值、最小值和总和,但我的大脑一片空白,如何为此构建分段树)。请举例说明

注意:我已经知道使用排序和二进制搜索的 nlogn 解决方案(针对每个查询)。我想了解如何利用段树来解决这个问题。

谢谢

【问题讨论】:

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


    【解决方案1】:

    我认为如果您为 数组元素 A 构建分段树,它不会起作用。您可以使用一些启发式/修剪,使用最大和最小的细分,但最终对于像这样的情况

    0, 10^6, 0, 10^6, 0, 10^6,...
    

    查询将退化为O(n),因为您需要深入每一片叶子。

    你应该做的是在可能值的范围上构建一个段树:对于每个值0<a<10^6,你记得数组A中有多少具有这个值的元素。例如对于

    A=[5,2,3,3,3,5,7,7] 
    

    出现的数组是

    f=[0,0,1,3,0,2,0,1,0,...]
    

    现在查询数组A 中小于x元素数,转换为查询元素总和在从0x 的出现数组f 中。

    您可以使用段树来回答此查询。

    但是,如果您在查询之前知道整个数组 - 这是一个非常无聊的案例 - 您可以在数组 f 上使用 prefix sum,预处理时间为 O(n),查询时间为 O(1)

    只有当数组 A 的查询和更新交错时,段树才有意义。

    如果查询和更新是交错的,我建议使用Fenwicktree,它不像段树那样灵活,但它正是针对这类问题量身定制的。它更容易实现、更快并且需要更少的内存。

    【讨论】:

      【解决方案2】:

      使用普通的段树不可能在 O(logn) 中回答这种类型的查询。 您需要使用小波树(也很少有其他数据结构可以回答此查询,但小波树最有趣)。如果您不了解此数据结构,此链接可能会有所帮助:

      https://codeforces.com/blog/entry/52854

      https://youtu.be/4aSv9PcecDw

      【讨论】:

        猜你喜欢
        • 2018-11-19
        • 1970-01-01
        • 2018-09-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-25
        • 2016-09-22
        相关资源
        最近更新 更多