100246.将元素分配到两个数组中 II
题目描述:
给你一个下标从 1 开始、长度为 n
的整数数组 nums
。
现定义函数 greaterCount
,使得 greaterCount(arr, val)
返回数组 arr
中 严格大于 val
的元素数量。
你需要使用 n
次操作,将 nums
的所有元素分配到两个数组 arr1
和 arr2
中。在第一次操作中,将 nums[1]
追加到 arr1
。在第二次操作中,将 nums[2]
追加到 arr2
。之后,在第 i
次操作中:
- 如果
greaterCount(arr1, nums[i]) > greaterCount(arr2, nums[i])
,将nums[i]
追加到arr1
。 - 如果
greaterCount(arr1, nums[i]) < greaterCount(arr2, nums[i])
,将nums[i]
追加到arr2
。 - 如果
greaterCount(arr1, nums[i]) == greaterCount(arr2, nums[i])
,将nums[i]
追加到元素数量较少的数组中。 - 如果仍然相等,那么将
nums[i]
追加到arr1
。
连接数组 arr1
和 arr2
形成数组 result
。例如,如果 arr1 == [1,2,3]
且 arr2 == [4,5,6]
,那么 result = [1,2,3,4,5,6]
。
返回整数数组 result
。
数据范围:
$3\le n \le 10^5, 1\le nums[i] \le 10^9$
题解:
关键在于如何求一个数组中大于 $val$ 的元素个数。如果是有序的,可以直接使用 upper_bound
解决。注意到 multiset
是有序的,可以用这个,但是这个返回的是迭代器,求 $it, multiset.end$ 之间的元素个数,只能用 distance
,这个复杂度是 $O(n)$ 的,太慢了。
考虑python中的 SortedList
,需要导入包from sortedcontainers import SortedList
,底层是对 list
的一些优化,返回的还是数组的下标。SortedList.bisect_right()
python中的二分查找,需要导入包 import bisect
。bisect_right
查找 >
,bisect_left
查找 >=
。
也有线段树的做法:
可以先对所有的数据排序,离散化,然后把离散化之后的数据作为数组下标,数组中记录出现的次数,这样的话,查询大于 val
的元素个数,只需要求 [val+1,n]
的后缀和。
考虑线段树单点修改,每次对 hash(nums[i])
下标加 1
。然后区间查询,查询区间的元素个数之和。
可以查询 [1, hash(nums[i])]
或者 [hash(nums[i]), n]
。
也可以使用树状数组的做法:
代码:
1 | import bisect |
1 | auto optimize_cpp_stdio = []() |
1 | auto optimize_cpp_stdio = []() |