AcWing 单调队列优化DP相关问题 1087. 修剪草坪

import sys
sys.stdin = open('data.txt', 'r')


from collections import deque

n, m = map(int, input().split())
arr = []
for i in range(n):
    arr.append(int(input()))

'''
dp(i)表示前i头牛的合法选择中最大总价值的数值
用最后一头牛的状态切分状态
1. 最后一头牛不选 子集1的最大价值就是dp(i-1)
2. 最后一头牛选,以结尾连续的牛个数进行子集划分, 设S(i)是前缀和
    最大价值是
    max {
        dp(i-2) + S(i) - S(i-1),
        dp(i-3) + S(i) - S(i-2),
        ......
        dp(i-m-1) + S(i) - S(i-m)        
    }
    那么只需要求i位置前面长度为m的滑动窗口中,dp(i-2)-S(i-1)这个序列在窗口中的最大值即可
'''

def solve(arr, n, m):
    if m <= 0:
        return 0

    S = [val for val in arr]
    for i in range(1, n):
        S[i] += S[i-1]

    que = deque()
    dp = [0] * n
    dp[0] = arr[0]
    for i in range(1, n):
        if i <= m-1:
            dp[i] = S[i]
        elif i == m:
            dp[i] = max(dp[i-1], S[i] - min(S[:m]))
        else:
            dp[i] = max(dp[i-1], que[0][1] + S[i])

        # 更新单调队列
        new_val = dp[i-1] - S[i]
        while len(que) > 0 and i - que[0][0] >= m:
            que.popleft()
        while len(que) > 0 and new_val >= que[-1][1]:
            que.pop()

        que.append( (i, new_val) )

    return dp[n-1]

print(solve(arr, n, m))




 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值