1 条题解
-
0
问题分析
本题是一道结合单调栈、线段树和树状数组(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的元素时:- 更新基础计数:总元素数
m减1,答案ans减1。 - 移除可见元素贡献:若
x是可见元素,减去其在可见集中的贡献,并从tr3、tr4和集合s中移除。 - 重新筛选可见元素:从
x的前一个可见元素位置开始,向右查询剩余元素的最小值,将符合条件的新可见元素加入集合,并累加其贡献。 - 更新数据结构:在
tr1、tr2和线段树中标记x为已删除。
4. 结果输出
初始计算完成后,输出初始答案,随后每次删除操作后输出更新后的答案。
关键公式与复杂度
- 可见元素判定:元素
a[i]是可见元素当且仅当它是其左侧所有元素中的最小值(通过单调栈维护)。 - 贡献计算:可见元素
a[stk[i]]的贡献为sum[a[stk[i]]] - suf[stk[i]],其中:sum[v]是值为v的元素总数suf[p]是位置p右侧的可见元素数
- 时间复杂度:
- 初始构建:
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
- 上传者