1 条题解

  • 0
    @ 2025-10-21 10:55:27

    问题分析

    本题是一道基于树状数组(Fenwick Tree)离线处理的区间查询问题,核心任务是高效统计每个查询区间内满足特定条件的元素数量。具体来说,对于每个查询 [l, r, x],需要计算区间内“上升点”的数量(即前一个元素小于当前元素的位置),并考虑边界条件的特殊情况。

    算法思路

    1. 数据预处理与离散化

    • 离散化:将原始数组 a 中的元素和所有查询的 x 值合并后排序去重,映射到 [0, m-1] 的范围(m 为不同值的数量)。这一步的目的是减少数值范围,便于后续按值分组处理。
    • 映射规则:使用 lower_bound 将原始值转换为离散化后的索引,存储在 ax 数组中。

    2. 上升点标记(tag 数组)

    • 上升点定义:对于位置 ii > 0),若 a[i-1] < a[i],则 i 是一个上升点。
    • 标记方式:对每个上升点 i,在 tag 数组中记录两个操作:
      • tag[a[i-1]] 中添加 (i, 1):表示当处理值 a[i-1] 时,在位置 i1
      • tag[a[i]] 中添加 (i, -1):表示当处理值 a[i] 时,在位置 i1。 这一设计用于后续按 x 筛选上升点。

    3. 离线查询处理

    • 查询排序:将所有查询按离散化后的 x 值升序排序,便于按值顺序批量处理。
    • 树状数组操作
      • 遍历离散化后的值 i,对每个值 i 先处理 tag[i] 中的所有标记(通过树状数组 add 函数更新位置的权重)。
      • 处理所有 x 值等于 i 的查询:
        • rangeSum(l+1, r) 计算区间 [l+1, r] 内的上升点数量(树状数组的区间和查询)。
        • 若区间左端点 l 的元素值大于 x,则额外加 1(边界条件修正)。

    4. 结果输出

    将处理后的查询结果按原始顺序输出。

    关键公式与复杂度

    1. 离散化映射: 设原始值集合为 V,排序去重后得到 v,则任意值 x 的离散化索引为:

      $$\text{idx}(x) = \text{lower\_bound}(v.begin(), v.end(), x) - v.begin() $$

      时间复杂度:O((n + q) log(n + q))

    2. 树状数组操作

      • 单点更新 add(x, y)O(log N),其中 N 为数组最大长度(1e6 + 1)。
      • 区间查询 rangeSum(x, y)O(log N),通过前缀和差实现。
    3. 总时间复杂度

      • 预处理与离散化:O((n + q) log(n + q))
      • 标记处理与查询:O(n log N + q log N + q log q)。 整体复杂度为 O((n + q) log(n + q)),适合处理 n, q ≤ 1e6 的规模。

    代码解析

    模块 功能描述
    树状数组 add 实现单点更新,sum 实现前缀和查询,rangeSum 计算区间和。
    离散化 合并数组元素与查询值,排序去重后映射为索引,减少数值范围。
    上升点标记 对每个上升点 i,在 tag 中记录位置 i 的权重变化,用于后续筛选。
    离线查询 x 排序查询,依次处理每个值对应的标记和查询,通过树状数组高效计算结果。

    算法的核心是通过离散化和离线处理,将分散的查询按值分组,结合树状数组的高效更新与查询能力,在大规模数据下快速统计满足条件的上升点数量,兼顾了时间效率和空间效率。

    • 1

    信息

    ID
    3646
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者