土地购买 HYSBZ - 1597 dp 斜率优化

题解

dp求解,考虑某个矩形长宽都被另一个完全包含则这个矩形可以不计算代价。将矩形按x降y升排列
转移方程 f[i] = min(f[i], f[j] + x[j + 1] * y[i]) 表示最大x*最大y,复杂度O(N^2),斜率优化。
f[i]通过j转移比k转移更优(k < j < i)斜率方程
(f[j] - f[k]) / (x[k + 1] - x[j + 1]) < y[i]
当前i点从j转移比k优则从t点从j转移比k优(j < i < t) 因为随着i的增大y也会增大 不等式恒成立

AC代码

#include <stdio.h>
#include <bits/stdc++.h>
#define fst first
#define sed second
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int N = 5e4 + 10;
ll f[N]; //f[i]前i项的最小代价
int ls[N], head, tail;
/*
转移方程f[i] = min(f[i], f[j] + x[j + 1] * y[i]) 最大x*最大y
f[i]通过j转移比k转移更优(k < j < i)斜率方程
(f[j] - f[k]) / (x[k + 1] - x[j + 1]) < y[i]
*/
struct node
{
	ll x, y;
	bool operator < (const node &oth) const //按x降y升排列
	{
		if (x != oth.x)
			return x > oth.x;
		return y > oth.y;
	}
}a[N];
inline ll up(int k, int j)
{
	//ll res = f[j] - f[k];
	return f[j] - f[k];
}
inline ll down(int k, int j)
{
	//ll res = a[k + 1].x - a[j + 1].x;
	return a[k + 1].x - a[j + 1].x;
}
int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	int n, m = 0;
	cin >> n;
	for (int i = 1; i <= n; ++i)
		scanf("%d%d", &a[i].x, &a[i].y);
	sort(a + 1, a + n + 1);
	int mx = 0; //最大的y
	for (int i = 1; i <= n; ++i) //消去xy完全被另一个包含的项
		if (a[i].y > mx)
			a[++m] = a[i], mx = a[i].y;
	ls[tail++] = 0; //可以通过0转移
	for (int i = 1; i <= m; ++i)
	{
		//i后移则只会导致y增大 不等式恒成立
		while (head + 1 < tail && up(ls[head], ls[head + 1]) <= a[i].y * down(ls[head], ls[head + 1]))
			head++; //淘汰表头
		int j = ls[head];
		f[i] = f[j] + (a[j + 1].x * a[i].y);
		while (head + 1 < tail && up(ls[tail - 2], ls[tail - 1]) * down(ls[tail - 1], i) >= up(ls[tail - 1], i) * down(ls[tail - 2], ls[tail - 1]))
			tail--; //淘汰表尾
		ls[tail++] = i; //插入
	}
	printf("%lld\n", f[m]);

	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值