您的位置:首页 > 其它

【BZOJ】【1597】【USACO 2008 Mar】土地购买

2015-03-12 16:34 176 查看

DP/斜率优化

  Orz Hzwer……

  想到排序了,但没想到其实可以将序列转化为x递增且y递减的序列……因为x是递增的,若y[i]>y[i-1]那么第i-1个就足够小……以至于可以在搞定第 i 个的同时顺便带走……

  这次仔细写一下斜率优化的过程吧~

  方程:$ f[i]=min\{ f[j]+x[i]*y[j+1] \} $

  若 $j>k$ 且 决策$j$更优,则有:\[ \begin{aligned} {f[j]+x[i]*y[j+1]} &< {f[k]+x[i]*y[k+1]} \\ {f[j]-f[k]} &< {x[i]*(y[k+1]-y[j+1])} \\ {\frac{ f[j]-f[k] }{ y[k+1]-y[j+1] }} &< {x[i]} \end{aligned} \]

  至此我们就可以用单调队列来维护决策序列了(一个凸壳)

/**************************************************************
Problem: 1597
User: Tunix
Language: C++
Result: Accepted
Time:108 ms
Memory:3036 kb
****************************************************************/

//BZOJ 1597
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
int getint(){
int v=0,sign=1; char ch=getchar();
while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
return v*=sign;
}
const int N=50010,INF=~0u>>2;
typedef long long LL;
/******************tamplate*********************/

struct node{
int x,y;
bool operator < (const node&b)const{
return x<b.x || (x==b.x && y<b.y);
}
}a
;
LL f
,x
,y
;
int q
;
double slop(int a,int b){
return double(f[b]-f[a])/(y[a+1]-y[b+1]);
}
int main(){
int n=getint(),m=0;
F(i,1,n) a[i].x=getint(),a[i].y=getint();
sort(a+1,a+n+1);
F(i,1,n){
while(m && a[i].y>=y[m]) m--;
x[++m]=a[i].x; y[m]=a[i].y;
}
int l=0,r=0;
F(i,1,m){
while(l<r && slop(q[l],q[l+1])<x[i])l++;
int t=q[l];
f[i]=f[t]+y[t+1]*x[i];
while(l<r && slop(q[r],i)<slop(q[r-1],q[r]))r--;
q[++r]=i;
}
printf("%lld\n",f[m]);
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: