Marvolo Gaunt's Ring CodeForces - 855B+线段树+维护区间最大值和最小值

题目链接:
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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值