P2900 [USACO08MAR]土地征用Land Acquisition

Description

农夫John准备扩大他的农场,他正在考虑N (1 <= N <= 50,000) 块长方形的土地. 每块土地的长宽满足(1 <= 宽 <= 1,000,000; 1 <= 长 <= 1,000,000). 每块土地的价格是它的面积,但FJ可以同时购买多快土地. 这些土地的价格是它们最大的长乘以它们最大的宽, 但是土地的长宽不能交换. 如果FJ买一块3×5的地和一块5×3的地,则他需要付5×5=25. FJ希望买下所有的土地,但是他发现分组来买这些土地可以节省经费. 他需要你帮助他找到最小的经费.

Input

* 第1行: 一个数: N

* 第2..N+1行: 第i+1行包含两个数,分别为第i块土地的长和宽

Output

* 第一行: 最小的可行费用.

Sample Input

4
100 1
15 15
20 5
1 100
输入解释:
共有4块土地.

Sample Output

500

HINT

FJ分3组买这些土地: 第一组:100×1, 第二组1×100, 第三组20×5 和 15×15 plot. 每组的价格分别为100,100,300, 总共500.


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1000000+5;
int read()
{
	int x=0,f=1;
	char ch;
	ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
	return x*f;
}
int n,a,b,c;
int w[maxn],q[maxn];
long long s[maxn],f[maxn];
long long g(int i)
{
	return a*s[i]*s[i]+b*s[i];
}
long long h(int j)
{
	return f[j]+a*s[j]*s[j]-b*s[j];
}
double slope(int j1,int j2)
{
	return (h(j1)-h(j2))/(2.0*a*(s[j1]-s[j2]));
}
long long js(int x)
{
	return a*x*x+b*x+c;
}
int main()
{
	int i;
	n=read();
	a=read();b=read();c=read();
	for(i=1;i<=n;i++)
		w[i]=read();
	for(i=1;i<=n;i++)
		s[i]=s[i-1]+w[i];
	int h=1,p=0;
	q[++p]=0;
	for(i=1;i<=n;i++)
	{
		while(p>h&&slope(q[h],q[h+1])<=s[i]) h++;
		int t=q[h];
		f[i]=f[t]+js(s[i]-s[t]);
		while(p>h&&slope(q[p],i)<slope(q[p-1],q[p])) p--;
		q[++p]=i;
	}
	printf("%lld",f[n]);
	return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值