1 条题解
-
0
题目分析
问题本质
统计所有连续子数组 中,满足平均价格 的子数组个数。
关键数学转化
平均数条件转化
对于子数组 ,平均价格条件为:
两边乘以长度 :
前缀和表示
令 ,则:
进一步转化
将不等式重组:
令 ,则问题转化为: 统计有多少对 满足 且
问题重新表述
现在问题变成:在数组 中(注意 ),统计有多少个逆序对 满足 且 。
算法框架
解法1:树状数组/线段树(推荐)
步骤1:预处理
- 计算前缀和
- 计算 ,特别地
- 得到数组
步骤2:离散化 由于 和 范围很大, 的值域可能很大,需要离散化:
- 将 排序去重,得到排名映射
- 将原值映射到 的整数范围
步骤3:树状数组统计 从左到右扫描 数组:
- 对于每个 ,查询树状数组中值 的元素个数
- 将 加入树状数组
- 累加所有查询结果
时间复杂度:
解法2:归并排序求"顺序对"
思路:
- 通常归并排序用于求逆序对()
- 这里需要求"顺序对"()
- 在归并过程中统计左半部分 右半部分的元素对
步骤:
- 对 数组进行归并排序
- 在合并过程中,当 时统计数量
- 递归统计左右子问题的答案
时间复杂度:
解法3:平衡树
思路:
- 使用平衡树(如C++的multiset)动态维护已处理的 值
- 对于每个新值 ,查询树中小于等于 的元素个数
- 将 插入平衡树
时间复杂度:
算法细节
离散化处理
由于 ,:
- 的范围可能达到 级别
- 必须离散化才能使用树状数组
- 离散化后值域变为
边界情况处理
- :必须包含,对应空前缀
- 重复值:多个 可能相等,需要正确处理
- 整数溢出:计算 时可能溢出,需要使用long long
统计公式推导
最终答案 = 所有满足 且 的对数
复杂度分析
时间复杂度
- 前缀和计算:
- 离散化排序:
- 树状数组操作:
- 总复杂度:
空间复杂度
- 存储前缀和和 数组:
- 离散化数组:
- 树状数组:
- 总空间:
特殊情况分析
值很大
如果 远大于所有 ,则大部分 为负数,答案可能很小。
值很小
如果 很小,几乎所有子数组都满足条件,答案接近 。
所有元素相等
如果所有 :
- 当 时,所有子数组都满足条件
- 当 时,没有子数组满足条件
实现考虑
数据结构选择
- 树状数组:代码简单,常数小,推荐使用
- 线段树:功能更强但代码复杂
- 归并排序:无需离散化,但代码较复杂
数据类型
- 使用64位整数避免溢出
- 最终答案可能达到 级别,需要用long long存储
优化技巧
- 离散化时使用vector和unique
- 树状数组大小设为离散化后的值域大小
- 注意数组下标从0还是1开始
总结
本题的核心在于将平均数问题转化为前缀和差分问题,再转化为逆序对统计问题。通过巧妙的数学转化,将原问题变为经典的顺序对计数问题,然后利用树状数组或归并排序在 时间内解决。关键难点在于发现 的构造和问题转化。
- 1
信息
- ID
- 4368
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者