CodeForces855B Marvolo Gaunt's Ring 思维题/dp/线段树留坑

15 篇文章 0 订阅
10 篇文章 0 订阅

题意:给你一串数的序列,给你三个数 p,q,r,问你怎样选择数列中的三个数,使得p·ai+q·aj+r·ak最大,其中i<=j<=k。
思路:可用线段树,但俺不会,就当个思维题看吧(据说这题当思维题做要快很多,而且代码短小精悍,当然我是参考了bin巨和hmgg的思路,确实niubility。
但是要说几点:inf要至少开到4e18,如果开到1e18是过不了的。
二是注意一下循环里的三句:aa那句是求出第一项p·ai的最大值 不断更新,第二句是求出前两项之和p·ai+q·aj的最大值,并不断更新,第三句是求三项p·ai+q·aj+r·ak的最大值,并不断更新。这样就类似于一个dp,但是不用开那么大的空间。
反正我看到这种题总是怵头的,当时还以为是区间dp啊balabla什么的,其实没那么麻烦。这种我还需要多练。
AC代码:

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3f
#define cl(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=5e5+10;
ll a[maxn];
int main(){
	ll n,p,q,r;
	cin>>n>>p>>q>>r;
	ll aa=-inf,bb=-inf,cc=-inf;
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
		aa=max(aa,p*a[i]);
		bb=max(bb,aa+q*a[i]);
		cc=max(cc,bb+r*a[i]);
	}
	printf("%lld",cc);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值