Farmer John is considering buying more land for the farm and has his eye on N (1 <= N <= 50,000) additional rectangular plots, each with integer dimensions (1 <= width_i <= 1,000,000; 1 <= length_i <= 1,000,000).ios
If FJ wants to buy a single piece of land, the cost is $1/square unit, but savings are available for large purchases. He can buy any number of plots of land for a price in dollars that is the width of the widest plot times the length of the longest plot. Of course, land plots cannot be rotated, i.e., if Farmer John buys a 3x5 plot and a 5x3 plot in a group, he will pay 5x5=25.git
FJ wants to grow his farm as much as possible and desires all the plots of land. Being both clever and frugal, it dawns on him that he can purchase the land in successive groups, cleverly minimizing the total cost by grouping various plots that have advantageous width or length values.ide
Given the number of plots for sale and the dimensions of each, determine the minimum amount for which Farmer John can purchase all優化
約翰準備擴大他的農場,眼前他正在考慮購買N塊長方形的土地。若是約翰單買一塊土 地,價格就是土地的面積。但他能夠選擇併購一組土地,併購的價格爲這些土地中最大的長 乘以最大的寬。好比約翰併購一塊3 × 5和一塊5 × 3的土地,他只須要支付5 × 5 = 25元, 比單買合算。 約翰但願買下全部的土地。他發現,將這些土地分紅不一樣的小組來併購能夠節省經費。 給定每份土地的尺寸,請你幫助他計算購買全部土地所需的最小費用。spa
輸入格式:code
* Line 1: A single integer: Nblog
* Lines 2..N+1: Line i+1 describes plot i with two space-separated integers: width_i and length_i排序
輸出格式:token
* Line 1: The minimum amount necessary to buy all the plots.get
There are four plots for sale with dimensions as shown.
The first group contains a 100x1 plot and costs 100. The next group contains a 1x100 plot and costs 100. The last group contains both the 20x5 plot and the 15x15 plot and costs 300. The total cost is 500, which is minimal.
--- $Sol:$
能夠發現對於兩塊土地$i$和$j$,若是$h[j]$\ge h[i]&&$l[j]\ge l[i]$,那麼$i$這塊土地是能夠被$j$一塊併購的,對答案沒有影響。因此咱們把土地按照$l[]$升序排序,而後一個個加入棧中,若是當前土地的$h$和$l$都比棧頂大,那麼就把棧頂彈出,而後加入當前土地。能夠發現咱們最後獲得的土地序列,$l[]$是遞增的,$h[]$是遞減的。 那麼咱們列出狀態轉移方程: $f[i]=\min\left(f[j]+l[i]*h[j+1]\right)$ 對於$k>j$,若$k$比$j$優,則有 $f[k]+l[i]*h[k+1]<=f[j]+l[i]*h[j+1]$ $\Rightarrow f[k]-f[j]<=l[i]*\left(h[j+1]-h[k+1]\right)$ 而後就能夠用斜率優化了
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; typedef long long LL; inline int read() { char c=getchar();int num=0,f=1; for(;!isdigit(c);c=getchar()) f=c=='-'?-1:f; for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num*f; } const int N=1e6+5; int n; LL f[N]; int q[N],h,t; LL a[N],b[N],top; struct Line { int a,b; bool operator < (const Line &A) const { return a==A.a?b<A.b:a<A.a; } }line[N]; inline LL Y(int k,int j) { return f[k]-f[j]; } inline LL X(int k,int j) { return b[j+1]-b[k+1]; } int main() { n=read(); for(int i=1;i<=n;++i) line[i].a=read(),line[i].b=read(); sort(line+1,line+n+1); a[top=1]=line[1].a,b[top]=line[1].b; for(int i=2;i<=n;++i) { while(top&&line[i].a>=a[top]&&line[i].b>=b[top]) --top; a[++top]=line[i].a,b[top]=line[i].b; } for(int i=1;i<=top;++i) { while(h<t&&Y(q[h+1],q[h])<=a[i]*X(q[h+1],q[h])) ++h; f[i]=f[q[h]]+a[i]*b[q[h]+1]; while(h<t&&Y(i,q[t])*X(q[t],q[t-1])<=Y(q[t],q[t-1])*X(i,q[t])) --t; q[++t]=i; } cout<<f[top]; return 0; }