【bzoj1597】土地购买 斜率优化dp

AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1597

【题解】

按照x,y递增排序,然后把可以和其它打包一起买的去掉

然后使得剩下一些y递减x递增的矩形

显然f[i]=min(f[j]+y[j+1]x[i])

然后再搞个斜率优化

方程是(f[j]-f[k])/(y[k+1]-y[j+1])<x[i]

然后维护一个下凸包

——转自hzwer

/*************
  bzoj 1597
  by chty
  2016.11.14
*************/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
#define MAXN 50010
#define FILE "read"
#define up(i,j,n) for(ll i=j;i<=n;i++)
namespace INIT{
	char buf[1<<15],*fs,*ft;
	inline char getc() {return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
	inline ll read(){
		ll x=0,f=1;  char ch=getc();
		while(!isdigit(ch))  {if(ch=='-') f=-1;  ch=getc();}
		while(isdigit(ch))  {x=x*10+ch-'0';  ch=getc();}
		return x*f;
	}
}using namespace INIT;
struct node{ll x,y;}a[MAXN];
ll n,len,head,tail,x[MAXN],y[MAXN],f[MAXN],q[MAXN];
bool cmp(node a,node b) {return a.x==b.x?a.y<b.y:a.x<b.x;}
void init(){
	n=read();
	up(i,1,n) a[i].x=read(),a[i].y=read();
	sort(a+1,a+n+1,cmp);
	up(i,1,n){
		while(len&&a[i].y>=y[len]) len--;
		x[++len]=a[i].x;  y[len]=a[i].y;
	}
}
inline double slop(ll j,ll k) {return (double)(f[j]-f[k])/(double)(y[k+1]-y[j+1]);}
void solve(){
	up(i,1,len){
		while(head<tail&&slop(q[head],q[head+1])<x[i])  head++;
		ll t=q[head];
		f[i]=f[t]+y[t+1]*x[i];
		while(head<tail&&slop(q[tail-1],q[tail])>slop(q[tail],i))  tail--;
		q[++tail]=i;
	}
	printf("%lld\n",f[len]);
}
int main(){
	freopen(FILE".in","r",stdin);
	freopen(FILE".out","w",stdout);
	init();
	solve();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值