📅  最后修改于: 2023-12-03 15:10:35.156000             🧑  作者: Mango
这个问题可以使用动态规划来解决。具体来说,我们可以定义 $dp[i][j]$ 为目前已经处理了前 $i$ 个元素,且将第 $i$ 个元素设为 $j$ 的最大值。具体转移方程如下:
$$ dp[i][j] = \max_{j - 1 \leq k \leq j + 1} dp[i - 1][k] + A[i][j] $$
其中 $A[i][j]$ 表示原数组第 $i$ 个位置上面的值是 $j$ 时对应的权值。容易注意到,这个转移方程的时间复杂度是 $\mathcal{O}(n k)$ 的,无法通过本题。
不过可以发现,上面的转移方程存在一定的单调性,因此我们可以使用单调队列来优化转移过程。具体来说,对于一个位置 $i$,设 $q_j$ 表示以转移 $dp[i-1][j]$ 时对应的最优选择 $k$ 为队列顶部元素,此时在推 $dp[i][j]$ 的时候可以直接取 $q_j$(这是单调队列优化的关键,有没有!!!)。具体细节可以看代码。
实现代码如下:
def solve(n: int, k: int, m: int):
a = [[0] * (k + 2) for _ in range(n + 1)]
for i in range(1, n + 1):
l, r, val = map(int, input().split())
for j in range(l, r + 1):
a[i][j] = val
dp = [[0] * (k + 2) for _ in range(n + 1)]
for j in range(1, k + 1):
dp[1][j] = a[1][j]
for i in range(2, n + 1):
q = []
for j in range(1, k + 1):
while q and q[0][0] + 1 < j:
q.pop(0)
dp[i][j] = dp[i - 1][q[0][1]] + a[i][j]
if q:
dp[i][j] = max(dp[i][j], dp[i - 1][q[-1][1]] + a[i][j])
while q and dp[i - 1][j - 1] - a[i][j - 1] > dp[i - 1][q[-1][1]] - a[i][q[-1][1]]:
q.pop()
q.append((j - 1, j))
if m in dp[i]:
return i
return -1
时间复杂度 $\mathcal{O}(n k)$,可以通过本题。