BZOJ1597: [Usaco2008 Mar]土地購買——斜率優化
阿新 • • 發佈:2018-05-25
zoj ret 代碼 size Go long while AI UC
題目大意:
將$n$個長方形分成若幹部分,每一部分的花費為部分中長方形的$max_長*max_寬$(不是$max_{長*寬}$),求最小花費
思路:
首先,可以被其他長方形包含的長方形可以刪去
然後我們按長方形的長度從小到大排序(排序後的長方形的寬度一定是從大到小)
設$f(i)$表示前i個長方形的最小花費,長方形的長和寬分別為$x(i),y(i)$,則有方程
$\Large f(i)=min(f(j)+x(i)*y(j+1))$
若對於某個$i$有$j$比$k$優,則
$f(j)+x(i)*y(j+1)\le f(k)+x(i)*y(k+1)$
化簡得$\frac{f(j)-f(k)}{y(k+1)-y(j+1)}\le x(i)$
維護下凸殼即可
代碼
#include<cstdio> #include<algorithm> using namespace std; #define maxn 50005 #define LL long long struct Node{ int x,y; bool operator < (const Node& a)const{ return x!=a.x?x<a.x:y<a.y; } }a[maxn]; int n,si,que[maxn],s,t=1; LL f[maxn]; LL calc(int i,int j){ return (f[i]-f[j]-1)/(a[j+1].y-a[i+1].y)+1; } void insert(int x){ while(s<t-1&&calc(x,que[t-1])<=calc(que[t-1],que[t-2]))t--; que[t++]=x; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&a[i].x,&a[i].y); } sort(a+1,a+n+1); for(int i=1;i<=n;i++){ while(si&&a[si].y<=a[i].y)si--; a[++si]=a[i]; }n=si; for(int i=1;i<=n;i++){ while(s<t-1&&calc(que[s+1],que[s])<=a[i].x)s++; int w=que[s]; f[i]=f[w]+1ll*a[i].x*a[w+1].y; insert(i); } printf("%lld",f[n]); return 0; }
BZOJ1597: [Usaco2008 Mar]土地購買——斜率優化