1 条题解

  • 0
    @ 2025-10-21 9:38:22

    问题分析

    本题是一道结合单调栈线段树树状数组(Fenwick Tree) 的复杂数据结构题,核心任务是维护一个动态序列,实时计算满足特定条件的元素对数量,并支持元素删除操作。通过分析代码可知,问题涉及序列中"可见"元素的判定和计数,以及删除元素后对可见元素集的动态更新。

    算法思路

    1. 初始可见元素集构建

    • 单调栈(stk:用于筛选序列中的"可见"元素。可见元素定义为从左到右遍历序列时,当前元素比栈顶元素小,即形成一个单调递减的序列。

      • 遍历序列时,弹出栈中所有大于当前元素的元素,剩余栈顶元素为当前元素的左侧可见前驱。
      • 最终栈中元素构成序列的可见元素集,存储在stk中。
    • 辅助数组预处理

      • sum[i]:值为i的元素在序列中出现的次数(后缀和)。
      • suf[i]:位置i右侧(含i)的可见元素数量。
      • Min[i]:从位置i到序列末尾的最小元素值。
    • 初始答案计算

      • 基础值为n(每个元素自身计数)。
      • 累加可见元素集中每个元素的贡献:sum[a[stk[i]]] - suf[stk[i]],表示该元素右侧比它小的非可见元素数量。

    2. 数据结构应用

    • 树状数组(fenwick

      • tr1:维护位置的存在性(1表示存在,0表示删除)。
      • tr2:维护元素值的存在性。
      • tr3:维护可见元素的位置存在性。
      • tr4:维护可见元素的值存在性。 这些结构用于高效查询区间内的元素数量。
    • 线段树(tr:维护序列中剩余元素的最小值,支持单点更新(删除元素时标记为无穷大)和区间最小值查询,用于删除操作后重新筛选可见元素。

    3. 动态删除操作处理

    当删除位置x的元素时:

    1. 更新基础计数:总元素数m减1,答案ans减1。
    2. 移除可见元素贡献:若x是可见元素,减去其在可见集中的贡献,并从tr3tr4和集合s中移除。
    3. 重新筛选可见元素:从x的前一个可见元素位置开始,向右查询剩余元素的最小值,将符合条件的新可见元素加入集合,并累加其贡献。
    4. 更新数据结构:在tr1tr2和线段树中标记x为已删除。

    4. 结果输出

    初始计算完成后,输出初始答案,随后每次删除操作后输出更新后的答案。

    关键公式与复杂度

    1. 可见元素判定:元素a[i]是可见元素当且仅当它是其左侧所有元素中的最小值(通过单调栈维护)。
    2. 贡献计算:可见元素a[stk[i]]的贡献为sum[a[stk[i]]] - suf[stk[i]],其中:
      • sum[v]是值为v的元素总数
      • suf[p]是位置p右侧的可见元素数
    3. 时间复杂度
      • 初始构建:O(n log n)(单调栈O(n) + 树状数组初始化O(n log n))。
      • 每次删除操作:O(log n + k log n),其中k是新加入的可见元素数(总k不超过n)。
      • 总复杂度:O(n log n + q log n),适合n, q ≤ 1e5的规模。

    代码解析

    模块 功能描述
    初始处理(getans 构建单调栈确定可见元素,计算初始答案,初始化树状数组。
    线段树操作 build初始化最小值线段树,update标记删除,query查询区间最小值。
    树状数组操作 四个fenwick对象分别维护位置、值、可见位置、可见值的存在性。
    删除处理 更新答案和数据结构,重新筛选可见元素并更新贡献。

    算法的核心是利用单调栈识别可见元素,结合树状数组和线段树高效维护元素状态和查询统计信息,实现动态删除下的实时答案更新,兼顾了时间效率和空间效率。

    • 1

    信息

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