【斜率优化】HYSBZ 1597 土地购买

通道

思路:x排序,去除无用点,会发现x升序,y降序,然后dp[i]=min(dp[k] + x[i] * y[k+1])

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 
 7 typedef long long ll;
 8 const int MAX_N = 50007;
 9 
10 template <class T>
11 inline bool rd(T &ret) {
12     char c; int sgn;
13     if(c = getchar() , c == EOF) return false;
14     while(c != '-' && (c < '0' || c > '9')) c = getchar();
15     sgn = (c == '-') ? -1 : 1;
16     ret = (c == '-') ? 0 : (c - '0');
17     while(c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
18     ret *= sgn;
19     return true;
20 }
21 
22 
23 struct Point {
24     ll x, y;
25     Point () {
26         
27     }
28     Point(ll _x, ll _y) {
29         x = _x; y = _y;
30     }
31     bool operator < (const Point &rhs) const {
32         return x < rhs.x || x == rhs.x && y < rhs.y;
33     }
34 };
35 
36 int n;
37 ll X[MAX_N], Y[MAX_N];
38 ll dp[MAX_N], st[MAX_N], head, tail;
39 Point a[MAX_N];
40 
41 ll cal(int x, int i) {
42     return dp[x] + Y[x + 1] * X[i];
43 }
44 
45 bool check(int i, int j, int k) {
46     return (dp[j] - dp[k]) * (Y[j + 1] - Y[i + 1]) > 
47     (dp[i] - dp[j]) * (Y[k + 1] - Y[j + 1]);
48 }
49 
50 int main() {
51     rd(n);
52     for (int i = 0; i < n; ++i)rd(a[i].x), rd(a[i].y);
53     sort(a, a + n);
54     int tot = 0;
55     for (int i = 0; i < n; ++i) {
56         while (tot > 0 && Y[tot] <= a[i].y) --tot;
57         Y[++tot] = a[i].y, X[tot] = a[i].x;
58     }
59     st[head = tail = 0] = 0;
60     for (int i = 1; i <= tot; ++i) {
61         while (head < tail && cal(st[head], i) >= cal(st[head + 1], i)) ++head;
62         dp[i] = cal(st[head], i);
63         if (i != tot) while (head < tail && check(i, st[tail], st[tail - 1])) --tail;
64         st[++tail] = i;
65     }
66     printf("%lld\n", dp[tot]);
67     return 0;
68 }
View Code

 

posted @ 2015-07-31 16:54  mithrilhan  阅读(239)  评论(0编辑  收藏  举报