LeetCode673 最长递增子序列的个数
贪心 + 前缀和 + 二分查找
\(q[i][]\) 数组表示所有能成为长度为 \(i\) 的最长上升子序列的末尾元素的值
\(cnt[i][j]\) 记录以 \(q[i][j]\) 为结尾的最长上升子序列的个数
class Solution:
def findNumberOfLIS(self, nums: List[int]) -> int:
q, cnt = [], []
for num in nums:
idx = self.bisearch(len(q), lambda i:q[i][-1] >= num)
if idx > 0:
k = self.bisearch(len(q[idx - 1]), lambda i:q[idx - 1][i] < num)
c = cnt[idx - 1][-1] - cnt[idx - 1][k]
else: c = 1
if idx == len(q):
q.append([num])
cnt.append([0, c])
else:
q[idx].append(num)
cnt[idx].append(cnt[idx][-1] + c)
return cnt[-1][-1]
def bisearch(self, n, f):
l, r = 0, n
while l < r:
mid = (l + r) // 2
if f(mid): r = mid
else: l = mid + 1
return l