题目链接:https://loj.ac/problem/10180#submit_code
题目大意:
思路:
dp[i]表示强制选i这个位置时1~ i的最小代价,dp[i]=min(dp[i-m]~dp[i-1])+ a[i], 因为前面必须放一个。
min(dp[i-m]~dp[i-1])可以方便的用单调队列优化,所以复杂度就变成O(n)了
答案就是min(dp[n-m+1]~dp[n])
#include <bits/stdc++.h>
#define LL long long
using namespace std;
int a[200005], dp[200005];
struct node{
int w, i;
}q[200005];
int main()
{
int n, m;
memset(dp, 0, sizeof(dp));
scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++){
scanf("%d", &a[i]);
}
int L=1, R=0;
//预处理
for(int i=1; i<=m; i++){
dp[i]=a[i];
while(L<=R&&q[R].w>=dp[i]){//单调性
R--;
}
q[++R]=node{dp[i], i};
}
//滑动窗口
for(int i=m+1; i<=n; i++){
while(L<=R&&q[L].i<(i-m)){//范围外
L++;
}
dp[i]=q[L].w+a[i];
while(L<=R&&q[R].w>=dp[i]){//单调性
R--;
}
q[++R]=node{dp[i], i};
}
int ans=(1<<30);
for(int i=n-m+1; i<=n; i++){
ans=min(ans, dp[i]);
}
printf("%d\n", ans);
return 0;
}