题解 P2627 【[USACO11OPEN]Mowing the Lawn G】

· · 题解

Mowing the Lawn G「单调队列优化DP」

博客食用效果更佳

思路分析

管理大大审核辛苦了qwq

Code

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 100010
#define ll long long
using namespace std;
inline ll read(){
    ll x = 0,f = 1;
    char ch =getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x * f;
}
ll n,k;
ll f[N][2],e[N],sum[N],q[N];
int main(){
    n = read(),k = read();
    for(int i = 1;i <= n;i++){
        e[i] = read();
        sum[i] = sum[i-1] + e[i];
    }
    int head = 0,tail = 1;//注意队首为0,要不你会默认最开始1不选是最优的
    q[tail] = 1;
    f[1][1] = e[1];
    for(int i = 2;i <= n;i++){
        while(head<=tail && i-q[head] > k)head++;
        f[i][1] = f[q[head]][0] + sum[i] - sum[q[head]];//既然在队首没被弹掉,肯定是最大的啦
        f[i][0] = max(f[i-1][0],f[i-1][1]);//这个直接转移就行
        while(head<=tail && f[i][0]-sum[i]>=f[q[tail]][0]-sum[q[tail]])tail--;
        q[++tail] = i;
    }
    printf("%lld\n",max(f[n][0],f[n][1]));
    return 0;
}