题意:给你一串数的序列,给你三个数 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;
}