# [Bzoj1597][Usaco2008 Mar]土地购买(斜率优化)

$dp[i]$为前$i$块土地的最少花费，$dp[i]=max(dp[i],dp[j]+h[j+1]*w[i])$。

$dp[j]+h[j+1]*w[i]\leq dp[k]+h[k+1]*w[i]$

$dp[j]-dp[k]\leq (h[k+1]-h[j+1])*w[i]$

$\tfrac{dp[j]-dp[k]}{h[k+1]-h[j+1]}\leq w[i]$

$\tfrac{dp[j]-dp[k]}{h[j+1]-h[k+1]}\geq- w[i]$

PS:因为以前吃过精度的坑，所以写斜率优化基本是移相相乘。

 1 #include<bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 const int maxn = 5e4 + 100;
5 struct node {
6     ll w, h;
7 }a[maxn], b[maxn];
8 bool cmp(node x, node y) {
9     return x.w == y.w ? x.h < y.h : x.w < y.w;
10 }
11 ll dp[maxn]; int q[maxn];
12 ll check1(int j, int k) {
13     return dp[j] - dp[k];
14 }
15 ll check2(int j, int k) {
16     return b[j + 1].h - b[k + 1].h;
17 }
18 int main() {
19     int n, cnt = 0;
20     scanf("%d", &n);
21     for (int i = 1; i <= n; i++)
22         scanf("%lld%lld", &a[i].w, &a[i].h);
23     sort(a + 1, a + 1 + n, cmp);
24     for (int i = 1; i <= n; i++) {
25         while (cnt != 0 && b[cnt].h <= a[i].h)
26             cnt--;
27         b[++cnt] = a[i];
28     }
29     int l = 0, r = 0;
30     for (int i = 1; i <= cnt; i++) {
31         while (l < r && check1(q[l], q[l + 1]) >= -b[i].w * check2(q[l], q[l + 1]))
32             l++;
33         dp[i] = dp[q[l]] + b[q[l] + 1].h * b[i].w;
34         while (l < r && check1(q[r - 1], q[r]) * check2(q[r], i) <= check1(q[r], i) * check2(q[r - 1], q[r]))
35             r--;
36         q[++r] = i;
37     }
38     printf("%lld\n", dp[cnt]);
39 }

posted @ 2019-09-21 17:58  祈梦生  阅读(142)  评论(0编辑  收藏  举报