有 n 个数,以及 p,q,r
要求找到三个数 使得 最大,其中
由于题目具有后效性,开始没有注意到,枚举 i∈[1,n] 使得 a[i]*p,然后用线段树找到 j∈[i,n] 使得 a[j]*q,再找到 k∈[j,n] 使得 a[k]*r,但是这样的做法是不对的,只能过到 12 个样例
因为每一步都是最优的,并不能代表整体最优
如果枚举 j,在从区间 [1,j] 和 [j,n] 分别找 i 和 k 的话这样是正确的,其余上述的做法不同的是,上述做法没有考虑后效性而缩小了区间范围,而这样枚举所有情况全部考虑到了
const int N=1e5+5;
int n,m;
int i,j,k;
int a[N];
struct Node
{
int l,r;
pll maxx,minn;
#define lson id<<1
#define rson id<<1|1
}t[N<<2];
void push_up(int id)
{
t[id].maxx=max(t[lson].maxx,t[rson].maxx);
t[id].minn=min(t[lson].minn,t[rson].minn);
}
void build(int l,int r,int id)
{
t[id].l=l,t[id].r=r;
if(l==r){ t[id].maxx={a[l],l},t[id].minn={a[l],l}; return ; }
else {
int mid=l+r>>1;
build(l,mid,lson);
build(mid+1,r,rson);
push_up(id);
}
}
pll query(int l,int r,int id,ll tag)
{
int L=t[id].l,R=t[id].r;
if(L>=l && r>=R) return tag>0?t[id].maxx:t[id].minn;
else{
int mid=L+R>>1;
if(tag>0){
pll ans={-9e18,l};
if(mid>=l) ans=max(ans,query(l,r,lson,tag));
if(r>=mid+1) ans=max(ans,query(l,r,rson,tag));
return ans;
} else{
pll ans={9e18,l};
if(mid>=l) ans=min(ans,query(l,r,lson,tag));
if(r>=mid+1) ans=min(ans,query(l,r,rson,tag));
return ans;
}
}
}
int main()
{
ll p,q,r;
while(~sd(n)){
sll(p),sll(q),sll(r);
forn(i,1,n) sd(a[i]);
build(1,n,1);
//forn(i,1,n) dbg(query(i,n,1,1).first);
ll ans,maxx=-9e18;
for(int i=1;i<=n;i++){
ans=q*a[i];
if(p){
pll tmp=query(1,i,1,p);
ans+=p*tmp.first;
}
if(r){
pll tmp=query(i,n,1,r);
ans+=r*tmp.first;
}
maxx=max(maxx,ans);
}
pll(maxx);
}
//PAUSE;
return 0;
}