一个合法的序列Bessie可以选择的是0[0], 1[0], 3[2], 2[1], 0[0]。(括号里的数表示钱数) 这样,可以得到的钱数为0+0+2+1+0 = 3。 如果Bessie选择一个序列开头为0, 1, 2, 3, ...,那么她就没办法跳回去了,因为她没办法再跳到一个之前没跳过的格子。序列0[0], 2[1], 4[-3], 5[4], 3[2], 1[0], 0[0]是最大化钱数的序列之一,最后的钱数为(0+1-3+4+2+0 = 4)。标签:har sharp www 整数 ios esc str line 选择
一个合法的序列Bessie可以选择的是0[0], 1[0], 3[2], 2[1], 0[0]。(括号里的数表示钱数) 这样,可以得到的钱数为0+0+2+1+0 = 3。 如果Bessie选择一个序列开头为0, 1, 2, 3, ...,那么她就没办法跳回去了,因为她没办法再跳到一个之前没跳过的格子。序列0[0], 2[1], 4[-3], 5[4], 3[2], 1[0], 0[0]是最大化钱数的序列之一,最后的钱数为(0+1-3+4+2+0 = 4)。题解:用f[i]表示既在去的时候跳到i,又在回来时调到i-1的最大钱数,再维护一个前缀和s[i],记录从1到i所有钱数大于0的格子的钱数和,可以列出方程
![]()
然后用单调队列维护一下就好了
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
int n,m,h,t;
int q[250010];
ll f[250010],v[250010],s[250010];
ll ans;
int main()
{
scanf("%d%d",&n,&m);
int i;
for(i=1;i<=n;i++) scanf("%lld",&v[i]);
h=1,t=0;
for(i=1;i<=n;i++)
{
s[i]=s[i-1]+max(0ll,v[i]);
while(h<=t&&i-q[h]>m) h++;
f[i]=f[q[h]]+s[i-2]-s[q[h]]+v[i]+v[i-1];
while(h<=t&&f[q[t]]-s[q[t]]<f[i-1]-s[i-1]) t--;
q[++t]=i-1;
}
ans=s[m];
for(i=1;i<=n;i++) ans=max(ans,f[i]+s[min(i+m-1,n)]-s[i]);
printf("%lld",ans);
return 0;
}
【BZOJ1915】[Usaco2010 Open]奶牛的跳格子游戏 DP+单调队列
标签:har sharp www 整数 ios esc str line 选择
原文地址:http://www.cnblogs.com/CQzhangyu/p/6412540.html