2018.09.10【BZOJ2442】修剪草坪(单调队列优化DP)

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/82595676

传送门


解析:

首先状态转移还是比较好想的。
f i , 0 / 1 表示考虑前 i 个时,选择第 i 个与不选第 i 个能够获得的最大效益。
我们维护一个 s u m 数组表示前缀和。

那么,状态转移方程也就呼之欲出了
f i , 0 = m a x ( f i 1 , 0 , f i 1 , 1 )
f i , 1 = m a x ( f j , 0 s u m j ) + s u m i ( i k <= j < i )
显然可以使用单调队列优化。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
#define st static

inline
ll getint(){
    re ll num=0;
    re char c;
    while(!isdigit(c=gc()));
    while(isdigit(c))num=(num<<1)+(num<<3)+(c^48),c=gc();
    return num;
}

int n,k;
ll sum[100002];
ll f[100002][2];
ll q[100002];
int head=1,tail=1;

signed main(){
    n=getint();
    k=getint();
    for(int re i=1;i<=n;++i)sum[i]=sum[i-1]+getint();

    for(int re i=1;i<=n;++i){
        f[i][0]=max(f[i-1][0],f[i-1][1]);
        while(q[head]<i-k&&head<=tail)++head;
        f[i][1]=f[q[head]][0]-sum[q[head]]+sum[i];
        while(f[i][0]-sum[i]>f[q[tail]][0]-sum[q[tail]]&&tail>=head)--tail;
        q[++tail]=i;
    }

    cout<<max(f[n][0],f[n][1]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/82595676