AcWing 1087. 修剪草坪
原题链接
中等
作者:
Anoxia_3
,
2021-05-03 22:33:02
,
所有人可见
,
阅读 298
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 100010;
int n , m , q[N];
LL a[N] , f[N] , s[N];
//f[i]表示到第i头牛的最大效率
//g[x] = f[x - 1] - s[x]
LL g(int x)
{
if(!x) return 0;
return f[x - 1] - s[x];
}
int main()
{
cin >> n >> m;
for(int i = 1 ; i <= n ; i++) cin >> s[i] , s[i] += s[i - 1];
int hh = 0 , tt = 0;
for(int i = 1 ; i <= n ; i++)
{
if(q[hh] < i - m) hh++;
/*
分析为什么if的条件是<i-m:
选第i头牛:f[i] = s[i] - s[i - j] + f[i - j - 1]
令g[x] = f[x - 1] - s[x],则f[i] = s[i] + g[i - j];其中j∈[1,m]
从中可以看出x是前缀和区间左边界-1,说明x最远可以取到窗口左边界-1,
又因为从第i头牛开始数,最远能数到第i-m+1,所以q[hh]最远可以取到i-m,所以上面if的条件是<i-m
*/
f[i] = max(f[i - 1] , f[q[hh] - 1] + s[i] - s[q[hh]]);
cout << i << ':' << q[hh] << ' ' << f[i] << endl;
while(hh <= tt && g(i) >= g(q[tt])) tt--;
q[++tt] = i;
}
cout << f[n] << endl;
}