1. 程式人生 > >BZOJ 1597: [Usaco2008 Mar]土地購買 斜率優化

BZOJ 1597: [Usaco2008 Mar]土地購買 斜率優化

pre esp 刪掉 for int using strong tput pan

1597: [Usaco2008 Mar]土地購買

Time Limit: 10 Sec Memory Limit: 162 MB

Description

農夫John準備擴大他的農場,他正在考慮N (1 <= N <= 50,000) 塊長方形的土地. 每塊土地的長寬滿足(1 <= 寬 <= 1,000,000; 1 <= 長 <= 1,000,000). 每塊土地的價格是它的面積,但FJ可以同時購買多快土地. 這些土地的價格是它們最大的長乘以它們最大的寬, 但是土地的長寬不能交換. 如果FJ買一塊3x5的地和一塊5x3的地,則他需要付5x5=25. FJ希望買下所有的土地,但是他發現分組來買這些土地可以節省經費. 他需要你幫助他找到最小的經費.

Input

* 第1行: 一個數: N

* 第2..N+1行: 第i+1行包含兩個數,分別為第i塊土地的長和寬

Output

* 第一行: 最小的可行費用.

Sample Input

4
100 1
15 15
20 5
1 100

輸入解釋:

共有4塊土地.

Sample Output

500

HINT

題解:

  按照X排序, 手動刪掉一些無影響的選擇

  剩下的都是 X增大,Y減小的矩陣

  那麽答案必須是選擇一段連續的矩陣了

  這個時候就可以DP

  他是有單調性的

#include<iostream>
#include
<cstring> #include<algorithm> #include<cstdio> #include<cmath> using namespace std; #define LL long long const int N = 1e5+10, inf = 1e9, mod = 1e9+7; struct ss{ LL x,y; }Q[N],tmp[N]; int cmp1(ss s1,ss s2) { if(s1.x == s2.x) return s1.y < s2.y; else return
s1.x < s2.x; } int cmp2(ss s1,ss s2) { if(s1.y == s2.y) return s1.x < s2.x; else return s1.y < s2.y; } int n,q[N]; LL dp[N]; int main() { scanf("%d",&n); for(int i = 1; i <= n; ++i) { scanf("%lld%lld",&Q[i].x,&Q[i].y); } sort(Q+1,Q+n+1,cmp1); int cnt = 0; for(int i = 1; i <= n; ++i) { while(cnt && tmp[cnt].y<=Q[i].y)cnt--; tmp[++cnt] = Q[i]; } n = cnt; for(int i = 1; i <= n; ++i) Q[i] = tmp[i],dp[i] = 1e15; dp[0] = 0; int l = 1,r = 2;q[1] = 0; q[2] = 1;dp[1] = 1LL*Q[1].x * Q[1].y; for(int i = 2; i <= n; ++i) { while(l < r && dp[q[l+1]] - dp[q[l]] < 1LL*(Q[q[l]+1].y - Q[q[l+1]+1].y) * Q[i].x) ++l; dp[i] = dp[q[l]] + 1LL*Q[i].x * Q[q[l]+1].y; while(l < r && (dp[q[r]]-dp[q[r-1]]) * 1LL*(Q[q[r]+1].y-Q[i+1].y) > (dp[i] - dp[q[r]]) * (Q[q[r-1]+1].y-Q[q[r]+1].y)) --r; q[++r] = i; } printf("%lld\n",dp[n]); return 0; }

BZOJ 1597: [Usaco2008 Mar]土地購買 斜率優化