Loading

题解 lg2034 选择数字

题意

给定一行n个非负整数a[1]..a[n]。现在你可以选择其中若干个数,但不能有超过k个连续的数字被选择。你的任务是使得选出的数字的和最大。

思路

\(f(i,0)\)表示考虑到数字\(i\)并选择\(i\)的最大和,\(f(i,1)\)表示考虑到数字\(i\)并选择\(i\)的最大和

那么

\[f(i,0)=min(f(i-1,0),f(i-1,1)) \]

\[f(i,1)=min(f(j,0)+sum_i-sum_j),i-k\leq j \leq i-1 \]

然后就可以单调队列优化了

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
int const MAXN=1e5+10;
int n,k;
int f[MAXN][2],e[MAXN],q[MAXN],d[MAXN];

signed main(){
	scanf("%lld%lld",&n,&k);
	for(int i=1;i<=n;i++){
		scanf("%lld",&e[i]);
		e[i]+=e[i-1];
	}
	int h=0,t=1;
	for(int i=1;i<=n;i++){
		f[i][0]=max(f[i-1][0],f[i-1][1]);
		while(h<=t && q[h]<i-k)h++;
		f[i][1]=e[i]+d[q[h]];
		d[i]=f[i][0]-e[i];
		while(h<=t && d[q[t]]<=d[i])t--;
		q[++t]=i;
	}
	printf("%lld\n",max(f[n][0],f[n][1]));
	return 0;
}
posted @ 2020-11-11 21:56  fpjo  阅读(88)  评论(0编辑  收藏  举报