您的位置:首页 > 其它

[BZOJ]2442:修剪草坪[DP+单调队列]

2016-12-06 13:37 253 查看


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……惭愧,实在是不应该。

f[i]表示不选i,且合法的最优解,因为f[i]=max{f[j]-sum[j]+sum[i-1]},对于j1<j2,并且f[j1]-sum[j1]<f[j2]-sum[j2],那么显然j1是没有任何价值的,对于这种问题,我们可以用一个单调队列来维护。

代码写的十分恶心,并且可能有很多bug……

#include<cstdio>
#include<cstring>
#define ll long long
const int Q=100005;
int n,k;
ll f[Q],a[Q],sum[Q];
ll Max(ll x,ll y) {return x>y?x:y;}
struct node
{
ll x;
int id;
}q[Q];
int st=1,ed=1;
int main()
{
//freopen("mowlawn.in","r",stdin);
//freopen("mowlawn.out","w",stdout);
sum[0]=0;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%I64d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
f[0]=0;
q[1].id=0;q[1].x=0;
for(int i=1;i<=n;i++)
{
while(st<ed && q[st].id<i-k-1) st++;
f[i]=sum[i-1]+q[st].x;
ll tt=f[i]-sum[i];
while(st<ed && q[ed].x<tt) ed--;
q[++ed].id=i;q[ed].x=tt;
}
ll ans=-1;
for(int i=0;i<=k;i++)
ans=Max(ans,f[n-i]+sum
-sum[n-i]);
printf("%I64d",ans);
}


f971
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: