luogu2627 修剪草坪

dp[i]表示1~i最大效率

记一下前缀和

转移就是f[i]=max(f[i],f[j-1]-sum[j])+sum[i] (i-k<=j<=i)

发现括号里的只与j有关 开一个单调队列维护一下

#include<cstdio>
#include<iostream>
#define ll long long
using namespace std;
//#pragma GCC optimize ("O3")
int n,k;
ll e[100010];
ll dp[100010];
ll sum[100010];
ll q[200010],head,tail;
ll num[200010];
long long calc(int a)
{
    num[a]=dp[a-1]-sum[a];
    while(head<=tail && num[q[tail]]<num[a])tail--;
    q[++tail]=a;
    while(head<=tail && q[head]<a-k)head++;
    return num[q[head]];
}
//f[i]=max(f[i],f[j-1]-sum[j])+sum[i]    (j 1~e)
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){scanf("%lld",&e[i]);sum[i]=sum[i-1]+e[i];}
    for(int i=1;i<=n;i++)dp[i]=calc(i)+sum[i];
    cout<<dp[n];
}

 

posted @ 2017-10-20 17:37  探险家Mr.H  阅读(150)  评论(0编辑  收藏  举报