【斜率优化】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 }