LC 2972. 统计移除递增子数组的数目 II
https://leetcode.cn/problems/count-the-number-of-incremovable-subarrays-ii/
这题还有一个简单的版本,内容是完全相同,只不过数据量更小。这题的数据量是在 10^5 左右,所以大致就是需要 O(nlgn) 的算法了。
假设我们选择了 \(a[i..n]\) 的话,然后我们需要挑选 \(a[0..j]\) , 需要满足几个条件:
- 首先是两个选择子数组都必须递增
- 然后就是 \(a[j] < a[i]\) .
- 结果就是有多少个j满足这个条件了。
在处理的时候需要做一个预处理,大致知道那些j的位置是有递增的,并且记录 `a[j]` 的值。 然后逆向处理,寻找有多少个 j 满足这个条件。 最后还需要考虑完全递增的情况,对于这种情况会重复计算prefix,在最后的结果上需要减去 (n+1)
class Solution: def incremovableSubarrayCount(self, nums: List[int]) -> int: n = len(nums) inc = [0] * n inc[0] = 1 for i in range(1, n): inc[i] = inc[i - 1] & (nums[i] > nums[i - 1]) # empty set. ans = 1 from sortedcontainers import SortedList sl = SortedList() for i in range(n): if inc[i]: sl.add(nums[i]) # prefix set. ans += 1 if inc[-1]: ans -= (n + 1) flag = 1 for i in reversed(range(n)): flag = flag & (nums[i] < nums[i + 1] if (i + 1) < n else 1) if not flag: break if inc[i]: sl.remove(nums[i]) size = sl.bisect_right(nums[i] - 1) + 1 # print(sl, nums[i:], size) ans += size return ans