bzoj1597 土地购买 动态规划&斜率优化

       最最基础的斜率优化(这么基础的斜率优化还WA这么多发鄙视,还好意思说)。

       显然如果a[i]>=a[j]且b[i]>=b[j],j是没有什么卵用的,直接去掉,那么如果将a降序排序,可以发现b一定是升序的。从而显然有方程,f[i]=min{f[j]+a[j+1]*b[i]}。那么对于j<k有斜率s(j,k)=(f[k]-f[k])/(a[j+1]-a[k+1]),当b[i]>=s(j,k)时k比j更优。那么当s(i,j)>s(j,k),且i<j<k时,可以证明j是无用的。单调队列维护这个斜率(似乎是叫做一个上凸包?),就可以O(1)转移了。

       P·S:然而我犯了sb错误,注意到上面a[j+1],显然这个a是处理后的,即a[j]和a[j+1]都应该是符合要求的。而我一开始写的时候只是保证了j是合法的。。。结果出数据死活出不出来,比如说:

2

7 10

9 2

原来的程序会输出88

然而在里面加一些会被舍去的解就会输出90。。o(╯□╰)o。。这怎么想得到啊。。。(果然还是万能的对拍大法)

看来还是要先把合法队列求出来呢。。

AC代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define ll long long
using namespace std;

int n,cnt,q[N]; ll f[N]; struct node{ ll x,y; }a[N];
bool cmp(node aa,node bb){ return aa.x>bb.x || (aa.x==bb.x && aa.y>bb.y); }
int main(){
	scanf("%d",&n); int i;
	for (i=1; i<=n; i++) scanf("%lld%lld",&a[i].x,&a[i].y);
	sort(a+1,a+n+1,cmp);
	for (i=1; i<=n; i++) if (a[i].y>a[cnt].y) a[++cnt]=a[i];
	int head=1,tail=1; q[1]=0;
	for (i=1; i<=cnt; i++){
		while (head<tail && a[i].y*(a[q[head]+1].x-a[q[head+1]+1].x)>=f[q[head+1]]-f[q[head]]) head++;
		f[i]=f[q[head]]+a[q[head]+1].x*a[i].y;
		while (head<tail && (f[q[tail]]-f[q[tail-1]])*(a[q[tail]+1].x-a[i+1].x)>(f[i]-f[q[tail]])*(a[q[tail-1]+1].x-a[q[tail]+1].x)) tail--;
		q[++tail]=i;
	}
	printf("%lld\n",f[cnt]);
	return 0;
}

by lych

2016.1.9

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值