luogu2627 修剪草坪
设dp[i]表示i位置不选且i之前的都合法的最小损失值。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
//dp[i] = min{dp[j]} + w[i] | i-j<=k+1 <=> i-k-1<=j<=i-1
int n, k, q[100005], l=1, r;
ll sum, dp[100005], w[100005];
int main(){
cin>>n>>k;
for(int i=1; i<=n; i++){
scanf("%lld", &w[i]);
sum += w[i];
}
for(int i=1; i<=n; i++){
while(l<=r && q[l]<i-k-1) l++;
while(l<=r && dp[q[r]]>dp[i-1]) r--;
q[++r] = i - 1;
dp[i] = dp[q[l]] + w[i];
}
ll minn=0x3f3f3f3f3f3f3f3f;
for(int i=n-k; i<=n; i++)
minn = min(minn, dp[i]);
cout<<sum-minn<<endl;
return 0;
}
可参考luogu琪露诺以加强理解
拙いものと思えども、
その手に握る其れこそが、
いつか幻想を生んでいく。