COGS-363-土地购买-斜率优化
生活随笔
收集整理的這篇文章主要介紹了
COGS-363-土地购买-斜率优化
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
描述
- 有 n(≤50000) 塊 (Xi*Yi) 的土地. 一些土地的購買價(jià)格是這些土地中長的最大值乘寬的最大值 (長寬不可顛倒). 求購買所有土地的最小花費(fèi).
- 將 n 個(gè)二元組 (x, y) 分組使每個(gè)組中的 max{x}*max{y} 的和最小.
分析
- 這里土地的順序是無所謂的, 所以憑直覺先按 x 升序排序.
然后去除無用的土地, 即如果一塊土地可以完全包含在另一塊土地里, 這一塊土地就不需要再考慮了(因?yàn)樗梢院秃笳叻衷谝唤M). 這一步可以用一個(gè)單調(diào)棧來實(shí)現(xiàn).
這時(shí) x 遞增, y 遞減.
- 得到轉(zhuǎn)移方程 : 由 j->i(j < i), f[i]=f[j?1]+Xi?Yj
- 意義就在于 j 和 i 之間的土地的長不大于 Xi 而寬不大于 Yj.
- O(n2)
- 斜率優(yōu)化 :
- 如果 j < k, j 不比 k 差, 則 f[j?1]+Xi?Yj≤f[k?1]+Xi?Yk
- 化簡得到 Xi≤f[k?1]?f[j?1]Yj?Yk
- 設(shè)上式 f[k?1]?f[j?1]Yj?Yk=g(j,k)
- 則如果 g(a,b)>g(b,c) 則 b 可以完全被舍棄. 證明如下
- 如果 g(a,b)≥Xi, 那么 a 優(yōu)于 b.
- 如果 g(a,b)<Xi, 那么 g(b,c)<Xi c 優(yōu)于 b.
- 所以可以用一個(gè)單調(diào)隊(duì)列來存儲(chǔ)當(dāng)前在考慮范圍內(nèi)的土地. 用隊(duì)尾的兩個(gè)結(jié)點(diǎn)和 i 的 X 和 Y 的值來維護(hù)單調(diào)隊(duì)列. 其實(shí)是判定隊(duì)尾結(jié)點(diǎn)可不可以刪除.
- 而在更新 f[i] 的答案時(shí), 則從隊(duì)頭選取. 如果 g(q[first],q[first+1])≥Xi 說明隊(duì)首元素是隊(duì)列中的最優(yōu)解(向后推就可以證明了). 否則 first 就應(yīng)該從隊(duì)列中刪除, 因?yàn)榇藭r(shí) q[first+1] 比 q[first] 優(yōu), 在 i 變大時(shí) Xi 也變大, 那么 g(q[first],q[first+1])<Xi 是一定成立的.
- O(n?logn)
代碼
https://code.csdn.net/snippets/647122
#include <cstdio> #include <algorithm> using namespace std;const int maxn = 50000 + 10;inline int getint() {int x = 0, f = 1;char ch = getchar();for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x*10 + ch-'0';return x * f; }struct Node {int x, y;bool operator < (const Node& rhs) const {if(x == rhs.x) return y < rhs.y;return x < rhs.x;} } A[maxn];int q[maxn]; long long f[maxn];double g(int a, int b) {return (double)(f[b-1]-f[a-1]) / (A[a].y-A[b].y); }int main() {freopen("acquire.in", "r", stdin);freopen("acquire.out", "w", stdout);int n = getint(), m;for(int i = 0; i < n; i++) {A[i].x = getint();A[i].y = getint();}sort(A, A + n);m = 0;for(int i = 0; i < n; i++) {while(m > 0 && A[m-1].y <= A[i].y) m--;A[m++] = A[i];}int first, last;first = last = 0;for(int i = 0; i < m; i++) {while(last-first > 1 && g(q[last-2], q[last-1]) > g(q[last-1], i)) last--;q[last++] = i;while(last-first > 1 && g(q[first], q[first+1]) < (double)A[i].x) first++;int j = q[first];f[i] = (long long)A[i].x * A[j].y + (j > 0 ? f[j-1] : 0);}printf("%lld\n", f[m-1]);return 0; }總結(jié)
以上是生活随笔為你收集整理的COGS-363-土地购买-斜率优化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 省选归来
- 下一篇: BestCoder-Round#38