您的位置:首页 > 运维架构

bzoj 2442: [Usaco2011 Open]修剪草坪 单调队列优化dp

2016-11-23 21:32 417 查看

题意

给出n个数,要求选出若干个数,满足没有连续超过k个数被选中且和最大。

k<=n<=100000

分析

设f[i]表示前i个数中选出若干个的最大和,sum[i]表示前i个数的和

显然f[i]=min(f[j−2]+sum[i]−sum[j−1])

那么这个东西只要拿单调队列来优化一下就好了。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define N 100005
#define ll long long
using namespace std;

int n,m,q
;
ll sum
,f
;

int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%lld",&sum[i]);
sum[i]+=sum[i-1];
}
f[1]=sum[1];
int head=1,tail=0;
ll ans=f[1];
for (int i=2;i<=n;i++)
{
f[i]=max(f[i-1],f[max(0,i-m-1)]+sum[i]-sum[max(0,i-m)]);
while (head<=tail&&q[head]<i-m+1) head++;
while (head<=tail&&f[i-2]+sum[i]-sum[i-1]>f[q[tail]-2]+sum[i]-sum[q[tail]-1]) tail--;
q[++tail]=i;
f[i]=max(f[i],f[q[head]-2]+sum[i]-sum[q[head]-1]);
ans=max(ans,f[i]);
}
printf("%lld",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: