3762:使数组元素相等的最小操作次数(2497 分)
目录
题目
给你一个整数数组 nums 和一个整数 k。
在一次操作中,你可以恰好将 nums 中的某个元素 增加或减少 k 。
还给定一个二维整数数组 queries,其中每个 queries[i] = [li, ri]。
对于每个查询,找到将 子数组 nums[li..ri] 中的 所有 元素变为相等所需的 最小 操作次数。如果无法实现,返回 -1。
返回一个数组 ans,其中 ans[i] 是第 i 个查询的答案。
子数组 是数组中一个连续、非空 的元素序列。
示例 1:
输入: nums = [1,4,7], k = 3, queries = [[0,1],[0,2]]
输出: [1,2]
解释:
一种最优操作方式:
i |
[li, ri] |
nums[li..ri] |
可行性 | 操作 | 最终nums[li..ri] |
ans[i] |
|---|---|---|---|---|---|---|
| 0 | [0, 1] | [1, 4] | 是 | nums[0] + k = 1 + 3 = 4 = nums[1] |
[4, 4] | 1 |
| 1 | [0, 2] | [1, 4, 7] | 是 | nums[0] + k = 1 + 3 = 4 = nums[1] |
[4, 4, 4] | 2 |
因此,ans = [1, 2]。
示例 2:
输入: nums = [1,2,4], k = 2, queries = [[0,2],[0,0],[1,2]]
输出: [-1,0,1]
解释:
一种最优操作方式:
i |
[li, ri] |
nums[li..ri] |
可行性 | 操作 | 最终nums[li..ri] |
ans[i] |
|---|---|---|---|---|---|---|
| 0 | [0, 2] | [1, 2, 4] | 否 | - | [1, 2, 4] | -1 |
| 1 | [0, 0] | [1] | 是 | 已相等 | [1] | 0 |
| 2 | [1, 2] | [2, 4] | 是 | nums[1] + k = 2 + 2 = 4 = nums[2] |
[4, 4] | 1 |
因此,ans = [-1, 0, 1]。
提示:
1 <= n == nums.length <= 4 × 1041 <= nums[i] <= 1091 <= k <= 1091 <= queries.length <= 4 × 104queries[i] = [li, ri]0 <= li <= ri <= n - 1
分析
#1 莫队+两个有序集合
- 莫队转移过程中,用两个有序集合分别维护区间较小/大的一半,及对应的和
- 注意必须用奇偶化排序,优化转移次数,否则会超时
- 时间复杂度: $O(n\sqrt{n}*logn)$
|
|
6551 ms
#2 莫队+值域分块
- 将值域离散化并分块,维护每块中的元素个数、元素总和、计数器
- 这样莫队转移过程中,只需要 O(1)的时间更新
- 计算时,遍历确定中位数 mid 在哪个块及块内位置,并统计 <= mid 的数之和 s1,再结合区间总和 s 即可求解
- 时间复杂度: $O(n\sqrt{n})$
|
|
3183 ms
#3 可持久化线段树
- 参照 可持久化线段树
- 建树时,遍历数组,t[i] 维护区间 [0,i] 的线段树版本的根节点
- 查询时,用 t[l] 和 t[r] 两个版本作差得到区间 [l,r] 的信息
- 时间复杂度:$O(nlogn)$
|
|
2627 ms
#4 划分树
- 参照 划分树
- 有点类似快排,将数组划分为较小/大的两半,并保持原有顺序
- 时间复杂度:$O(nlogn)$
|
|
2871 ms
#5 整体二分
- 参照 整体二分
- 其实就是将划分树的 build 和 query 一起进行
- 时间复杂度:$O(nlogn)$
解答
|
|
2720 ms