P2900 [USACO08MAR]Land Acquisition G

题目描述

\(Farmer\ John\)准备扩大他的农场,眼前他正在考虑购买\(N\)块长方形的土地。

如果\(FJ\)单买一块土地,价格就是土地的面积。但他可以选择并购一组土地,并购的价格为这些土地中最大的长乘以最大的宽。比如\(FJ\)并购一块\(3\times 5\) 和一块 \(5 \times 3\)的土地,他只需要支付\(5 \times 5=25\)元,比单买合算。

\(FJ\)希望买下所有的土地。他发现,将这些土地分成不同的小组来并购可以节省经费。 给定每份土地的尺寸,请你帮助他计算购买所有土地所需的最小费用。

题解

很容易想到如果一块土地的长和宽都比另一块小,那么这两块土地合并一下并按照大的那块土地计算比分开计算优。

所以我们先将土地按照长度从小到大排序,再对它们的高度维护一个单调递减栈,最后在栈中的土地才是有意义的。

对于这些土地,我们进行\(dp\),设\(f[i]\)表示考虑到第\(i\)块土地的最小费用,状态转移方程\(f[i] = min(f[i], f[j] + h[j + 1] * l[i])[1 \leq j < i]\)
,这个转移过程是\(O(n ^2)\)的,显然不可行。

所以我们考虑斜率优化,假设\(1\leq k < j < i\),且对于\(i\)来说,\(j\)\(k\)优,那么

\(f[j] + h[j + 1] * l[i] \leq f[k] + h[k + 1] * l[i]\)

\(f[j] - f[k] \leq (h[k + 1] - h[j + 1]) * l[i]\)

\(\frac{f[j] - f[k]}{- h[j + 1] - (- h[k + 1])} \leq l[i]\)

所以以此为判断条件弹出不优的队首并依次更新即可。

#include <iostream>
#include <cstdio>
#include <algorithm>
#define ll long long
#define int long long
using namespace std;
const int N = 50005;
int n, top, sta[N], q[N], l, r;
ll f[N];
struct node{int x, y;}a[N], b[N];
inline int read()
{
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
bool cmp(const node & a, const node & b) {return a.x < b.x;}
int X(int i) {return - b[i + 1].y;}
ll Y(int i) {return f[i];}
double slope(int i, int j) {return (double)(Y(i) - Y(j)) / (double)(X(i) - X(j));}
void work()
{
	n = read();
	for(int i = 1; i <= n; i ++) {a[i].x = read(); a[i].y = read();}
	sort(a + 1, a + n + 1, cmp);
	for(int i = 1; i <= n; i ++)
	{
		while(top && a[sta[top]].y <= a[i].y) top --;
		sta[++ top] = i;
	}
	for(int i = 1; i <= top; i ++) b[i] = a[sta[i]];
	q[l = r = 1] = 0;
	for(int i = 1; i <= top; i ++)
	{
		while(l < r && slope(q[l], q[l + 1]) <= b[i].x) l ++;
		f[i] = f[q[l]] + (ll)b[q[l] + 1].y * b[i].x;
		while(l < r && slope(q[r - 1], q[r]) >= slope(q[r - 1], i)) r --;
		q[++ r] = i;
	}
	printf("%lld\n", f[top]);//top
}
signed main() {return work(), 0; }

猜你喜欢

转载自www.cnblogs.com/Sunny-r/p/12610906.html