【BZOJ】【1597】【USACO 2008 Mar】土地购买
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} \]
至此我们就可以用单调队列来维护决策序列了(一个凸壳)
1 /************************************************************** 2 Problem: 1597 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:108 ms 7 Memory:3036 kb 8 ****************************************************************/ 9 10 //BZOJ 1597 11 #include<cmath> 12 #include<vector> 13 #include<cstdio> 14 #include<cstring> 15 #include<cstdlib> 16 #include<iostream> 17 #include<algorithm> 18 #define rep(i,n) for(int i=0;i<n;++i) 19 #define F(i,j,n) for(int i=j;i<=n;++i) 20 #define D(i,j,n) for(int i=j;i>=n;--i) 21 #define pb push_back 22 using namespace std; 23 int getint(){ 24 int v=0,sign=1; char ch=getchar(); 25 while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();} 26 while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();} 27 return v*=sign; 28 } 29 const int N=50010,INF=~0u>>2; 30 typedef long long LL; 31 /******************tamplate*********************/ 32 33 struct node{ 34 int x,y; 35 bool operator < (const node&b)const{ 36 return x<b.x || (x==b.x && y<b.y); 37 } 38 }a[N]; 39 LL f[N],x[N],y[N]; 40 int q[N]; 41 double slop(int a,int b){ 42 return double(f[b]-f[a])/(y[a+1]-y[b+1]); 43 } 44 int main(){ 45 int n=getint(),m=0; 46 F(i,1,n) a[i].x=getint(),a[i].y=getint(); 47 sort(a+1,a+n+1); 48 F(i,1,n){ 49 while(m && a[i].y>=y[m]) m--; 50 x[++m]=a[i].x; y[m]=a[i].y; 51 } 52 int l=0,r=0; 53 F(i,1,m){ 54 while(l<r && slop(q[l],q[l+1])<x[i])l++; 55 int t=q[l]; 56 f[i]=f[t]+y[t+1]*x[i]; 57 while(l<r && slop(q[r],i)<slop(q[r-1],q[r]))r--; 58 q[++r]=i; 59 } 60 printf("%lld\n",f[m]); 61 return 0; 62 }