COGS锯木厂选址(斜率优化)

这道题,需要选两个锯木厂,标定了选的份数,以前做的题都是可以分成任意的分数

实际上,这道题n^2枚举锯木厂的位置,O( 1 ) 计算,找出最大值。


算是斜率优化,感觉不是特别好说是斜率优化dp,因为这道题,当确定了第二个锯木厂,第一个锯木厂的选择是有决策单调性,其实斜率优化就是用了处理决策单调性的问题决策选取的,这道题推式子可以推出来斜率式,能推出斜率的式子,就可以来用单调队列维护决策处理单调性了



#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;

ll sum[200505],dis[200505],f[200505],ans=20000000005,s[200505];
int n,q[200505],head,tail;
ll getup(int j,int k)
{
	return dis[j+1]*sum[j]-dis[k+1]*sum[k];
}
ll getdown(int j,int k)
{
	return dis[j+1]-dis[k+1];
}
ll getdp(int i,int j)
{
	return -dis[j+1]*(sum[i]-sum[j])  +   
		   s[n]-dis[i+1]*(sum[n]-sum[i]);
}
int main()
{
	freopen("two.in","r",stdin);
	freopen("two.out","w",stdout);
	
	scanf("%d",&n);
	for (int i=n;i>=1;i--) scanf("%lld%lld",&sum[i],&dis[i]);
	
	for (int i=1;i<=n;i++) dis[i]+=dis[i-1],sum[i]+=sum[i-1];
	for (int i=1;i<=n;i++) s[i]=s[i-1]+(sum[i]-sum[i-1])*dis[i];
	
	head=tail=1;
	q[head]=0;
	
	f[0]=0;//?
	
	for (int i=1;i<n;i++)
	{
		while (head<tail &&
		getup(q[head+1],q[head])<sum[i]*getdown(q[head+1],q[head])
		) head++;
		
		f[i]=getdp(i,q[head]);
		
		while (head<tail && 
		getup(i,q[tail])*getdown(q[tail],q[tail-1])<
		getup(q[tail],q[tail-1])*getdown(i,q[tail])
		) tail--;
		
		q[++tail]=i;
		ans=min(ans,f[i]);
	}
	
	printf("%lld",ans);
	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值