【牛客7872 C变强的秘药】dp

【牛客7872 C变强的秘药】dp

传送门

题意

给n个数,按这个n个数给出的顺序取数,每一次至少取k个数,每一次取数的收益是取的序列后三个数之积 - 前三个数之积。例如我本次取a[1]~a[10],我能得到的收益是a[10] * a[9] * a[8] - a[1] * a[2] * a[3]。求怎么取能获得最大收益?

题解

dp[i]代表以 i 为取的某一次的右端点时,答案的最大值是多少。那么我们求的就是dp[n],因为显而易见n一定是某一次取的右端点。
考虑这个答案是由几部分组成的
是由3部分组成的,首先第一部分是 a [ i ] ∗ a [ i − 1 ] ∗ a [ i − 2 ] a[i] * a[i-1] * a[i-2] a[i]a[i1]a[i2],这一部分是雷打不动的
那另外两部分就是与 i i i相对于的这一次的左端点 j j j会带来的收益 − a [ j ] ∗ a [ j + 1 ] ∗ a [ j + 2 ] -a[j]*a[j+1]*a[j+2] a[j]a[j+1]a[j+2]以及dp[j-1]
由于第一部分是雷打不动的,所以想要让 d p [ i ] dp[i] dp[i]尽可能大,只能让 d p [ j − 1 ] − a [ j ] ∗ a [ j + 1 ] ∗ a [ j + 2 ] dp[j-1]-a[j]*a[j+1]*a[j+2] dp[j1]a[j]a[j+1]a[j+2]这一部分尽可能大
也就是需要枚举一个左端点j,求出上式的最大值即可
由于n的数据范围是1e7,因此上述做法显然是 n 2 n^2 n2的做法,优化一下就是,一边更新dp值,一边维护我们想要的这个最大值,即可优化成O(n)的

需要注意的是,我们转移时用到的 d p [ j − 1 ] , d p [ j − 1 ] dp[j-1],dp[j-1] dp[j1]dp[j1]就代表着 j − 1 j-1 j1是某一次取的右端点,又由于每一次至少取k个,所以, j − 1 j-1 j1必须>k,所以 i − k i-k ik必须 > k >k >k才能开始维护我们想要的那个最大值,一开始维护值应该初始化为-a[1] * a[2] * a[3]

Code

/****************************
* Author : W.A.R            *
* Date : 2020-10-30-19:58   *
****************************/
/*
*/
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<stack>
#include<string>
#include<set>
#define IOS ios::sync_with_stdio(false)
#define show(x) std:: cerr << #x << " = " << x << std::endl;
#define mem(a,x) memset(a,x,sizeof(a))
#define Rint register int
using namespace std;
typedef long long ll;
const int maxn=1e7+100;

ll dp[maxn],a[maxn];
int main(){
	int n,k;scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++){scanf("%lld",&a[i]);}
	ll res=-a[1]*a[2]*a[3];
	for(int i=k;i<=n;i++){
		if(i-k>=k)res=max(res,dp[i-k]-a[i-k+1]*a[i-k+2]*a[i-k+3]);
		dp[i]=res+a[i]*a[i-1]*a[i-2];
	}
	printf("%lld\n",dp[n]);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值