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

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

       显然如果a[i]>=a[j]且b[i]>=b[j],j是没有什么卵用的,直接去掉,那么如果将a降序排序,可以发现b一定是升序的。从而显然有方程,f[i]=min{f[j]+a[j+1]*b[i]}。那么对于j=s(j,k)时k比j更优。那么当s(i,j)>s(j,k),且i

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

2

7 10

9 2

原来的程序会输出88

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

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

AC代码如下:

#include
#include
#include
#include
#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=f[q[head+1]]-f[q[head]]) head++;
		f[i]=f[q[head]]+a[q[head]+1].x*a[i].y;
		while (head(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

你可能感兴趣的:(bzoj)