题目链接:
Marvolo Gaunt’s Ring CodeForces - 855B
题目大意:
给定一段序列:a1,a2,a3,……an,
给定三个数:p,q,r(注意数据范围,代码里ans=-1e18,就wrong在了第23个样例上了,开到-4e18就ok了)
求ai*p+aj*q+ak*r的最大值,且要求i<=j<=k;
数据范围: 1 ≤ n ≤ 105
时间限制: 2000 ms
最暴力的方法:从1-->n枚举每个数作为aj,枚举[1,j]里的每个数作为ai,枚举[j,n]里的每个数作为ak,计算并比较
当aj固定,只需找出最大的ai*p和ak*r即可;
这里需要讨论下,如果p>=0,在[1,j]里找最大的ai;如果p<0,在[1,j]里找最小的ai;
r如上。
这样的时间复杂度仅仅是:n*log(n)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int num=1e5+10;
struct node
{
int L,R;
LL mi,ma;
}a[num<<2];
LL d[num];
void update(int k)
{
a[k].ma=max(a[k<<1].ma,a[k<<1|1].ma);
a[k].mi=min(a[k<<1].mi,a[k<<1|1].mi);
return ;
}
void build(int k,int L,int R)
{
a[k].L=L;a[k].R=R;
a[k].ma=-4e18;a[k].mi=4e18;
if(L==R)
{
a[k].ma=a[k].mi=d[L];
return ;
}
int mid=(L+R)>>1;
build(k<<1,L,mid);
build(k<<1|1,mid+1,R);
update(k);
return ;
}
LL search_mi(int k,int L,int R)
{
if(a[k].L>=L&&a[k].R<=R)
{
return a[k].mi;
}
int mid=(a[k].L+a[k].R)>>1;
LL ans=4e18;
if(L<=mid) ans=min(ans,search_mi(k<<1,L,R));
if(R>mid) ans=min(ans,search_mi(k<<1|1,L,R));
return ans;
}
LL search_ma(int k,int L,int R)
{
if(a[k].L>=L&&a[k].R<=R)
{
return a[k].ma;
}
int mid=(a[k].L+a[k].R)>>1;
LL ans=-4e18;
if(L<=mid) ans=max(ans,search_ma(k<<1,L,R));
if(R>mid) ans=max(ans,search_ma(k<<1|1,L,R));
return ans;
}
int main()
{
LL n,p,q,r;
scanf("%lld%lld%lld%lld",&n,&p,&q,&r);
build(1,1,n);
for(int i=1;i<=n;i++)
scanf("%lld",&d[i]);
build(1,1,n);
LL le,re,ans=-4e18;
for(int i=1;i<=n;i++)
{
le= p>=0 ? search_ma(1,1,i) : search_mi(1,1,i);
re= r>=0 ? search_ma(1,i,n) : search_mi(1,i,n);
ans=max(ans,p*le+q*d[i]+r*re);
}
printf("%lld",ans);
return 0;
}