BZOJ-2442: [Usaco2011 Open]修剪草坪

[文章目录]

Description

在一年前赢得了小镇的最佳草坪比赛后,FJ变得很懒,再也没有修剪过草坪。现在,新一轮的最佳草坪比赛又开始了,FJ希望能够再次夺冠。然而,FJ的草坪非常脏乱,因此,FJ只能够让他的奶牛来完成这项工作。FJ有N(1 <= N <= 100,000)只排成一排的奶牛,编号为1...N。每只奶牛的效率是不同的,奶牛i的效率为E_i(0 <= E_i <= 1,000,000,000)。靠近的奶牛们很熟悉,因此,如果FJ安排超过K只连续的奶牛,那么,这些奶牛就会罢工去开派对:)。因此,现在FJ需要你的帮助,计算FJ可以得到的最大效率,并且该方案中没有连续的超过K只奶牛。

经典的dp,记忆中2017冬令营好像讲了。
dp[i]表示[1,i]区间合法且第i个牛被扔掉的最小扔掉的牛的效率和。
方程:dp[i]=min(dp[j]+w[i])。j属于[i-k,i-1],单调队列优化一下就好了。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
ll sum,dp[101000],ans=100000000000000ll;
int n,k,w[101000],q[101000];
int main()
{
    scanf("%d%d",&n,&k); k++;
    for(int i=1;i<=n;i++) scanf("%d",w+i),sum+=w[i];
    int h=1,t=1;
    for(int i=1;i<=n;i++)
    {
        while(q[h]<i-k) h++;
        dp[i]=dp[q[h]]+w[i];
        while(dp[q[t]]>=dp[i]) t--;
        q[++t]=i;
    }
    for(int i=n;i>n-k&&i>=0;i--)
        ans=min(ans,dp[i]);
    printf("%lld\n",sum-ans);
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注