P2900 [USACO08MAR]Land Acquisition G
阿新 • • 發佈:2020-11-04
Solution
發現對於一塊土地 \(x\) 和 \(y\) ,如果 \(l_y\geq l_x,h_y\geq h_x\) ,那麼把 \(x\) 和 \(y\) 合在一組對答案是不會更劣的。
將土地按照長度和寬度排序,維護一個棧,將有必要存在的土地留下。
在最優決策下,每一組土地都是連續的。因為如果有 \(x,y,z\) 三塊連續土地,並且 \(l_x<l_y<l_z,h_x>h_y>h_z\) ,把 \(x\) 和 \(z\) 一組, \(y\) 自己一組,花費為 \(h_x\cdot l_z+h_y\cdot l_y\) ,三個一組花費是 \(h_x\cdot l_z\)
考慮DP。設 \(f_i\) 表示前 \(i\) 個土地的最小費用,易得: \(f_i=\min\{f_i,f_{j}+h_{j+1}\cdot l_{i}\}\) ,但是時間複雜度為 \(O(n^2)\) ,過不去,考慮優化。
用斜率優化。設 \(k=h_{j+1},b=f_j\) ,那麼直線為 \(y=kx+b\) ,那麼之前的轉移方程就相當於求 \(x=l_i\) 時的 \(y_{min}\)
Code
#include<cmath> #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #define int long long using namespace std; const int N=5e4+10; int n,a[N],b[N],f[N],q[N],hd,tl,stk[N],top; struct node{ int a,b; bool operator < (const node &x) { return a==x.a?b<x.b:a<x.a; } }p[N]; inline int slope(int p,int t){ return f[p]+a[t]*b[p+1]; } inline bool cross(int t1,int t2,int i){ return 1ll*(f[t1]-f[t2])*(b[i+1]-b[t1+1])<1ll*(f[i]-f[t1])*(b[t1+1]-b[t2+1]); } signed main(){ scanf("%lld",&n); for(int i=1;i<=n;i++) scanf("%lld%lld",&p[i].a,&p[i].b); sort(p+1,p+n+1); stk[++top]=1; for(int i=2;i<=n;i++){ while(top&&p[i].b>=p[stk[top]].b) --top; stk[++top]=i; } n=top; for(int i=1;i<=n;i++) a[i]=p[stk[i]].a,b[i]=p[stk[i]].b; hd=tl=0; for(int i=1;i<=n;i++){ while(hd<=tl&&slope(q[hd],i)>slope(q[hd+1],i)) ++hd; f[i]=f[q[hd]]+a[i]*b[q[hd]+1]; while(hd<=tl&&cross(q[tl],q[tl-1],i)) --tl; q[++tl]=i; } printf("%lld\n",f[n]); return 0; }