很裸的斜率优化呀。
维护直线
#include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ALL(x) (x).begin(), (x).end() #define fio ios::sync_with_stdio(false); cin.tie(0); using namespace std; const int N = 1e6 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-8; const double PI = acos(-1); template<class T, class S> inline void add(T &a, S b) {a += b; if(a >= mod) a -= mod;} template<class T, class S> inline void sub(T &a, S b) {a -= b; if(a < 0) a += mod;} template<class T, class S> inline bool chkmax(T &a, S b) {return a < b ? a = b, true : false;} template<class T, class S> inline bool chkmin(T &a, S b) {return a > b ? a = b, true : false;} mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); namespace LC { /** * Description: Container where you can add lines of the form kx+m, and query maximum values at points x. * Time: O(log N) */ struct Line { mutable LL k, m, p; bool operator < (const Line& o) const { return k < o.k; } bool operator < (LL x) const { return p < x; } }; struct LineContainer : multiset<Line, less<>> { // (for doubles, use inf = 1/.0, div(a,b) = a/b) const LL inf = LLONG_MAX; LL div(LL a, LL b) { // floored division return a / b - ((a ^ b) < 0 && a % b); } bool isect(iterator x, iterator y) { if (y == end()) { x->p = inf; return false; } if (x->k == y->k) x->p = x->m > y->m ? inf : -inf; else x->p = div(y->m - x->m, x->k - y->k); return x->p >= y->p; } void add(LL k, LL m) { auto z = insert({k, m, 0}), y = z++, x = y; while (isect(y, z)) z = erase(z); if (x != begin() && isect(--x, y)) isect(x, y = erase(y)); while ((y = x) != begin() && (--x)->p >= y->p) isect(x, erase(y)); } LL query(LL x) { assert(!empty()); auto l = *lower_bound(x); return l.k * x + l.m; } }; } int n; LL dp[N]; struct Node { int x, y; LL v; bool operator < (const Node &rhs) const { return x < rhs.x; } } a[N]; int main() { scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%d%d%lld", &a[i].x, &a[i].y, &a[i].v); } sort(a + 1, a + 1 + n); LC::LineContainer cont; cont.add(0, 0); LL ans = 0; for(int i = 1; i <= n; i++) { int x = a[i].x, y = a[i].y; LL v = a[i].v; dp[i] = cont.query(y) + 1LL * x * y - v; cont.add(-x, dp[i]); chkmax(ans, dp[i]); } printf("%lld ", ans); return 0; } /* */
维护凸包
#include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ALL(x) (x).begin(), (x).end() #define fio ios::sync_with_stdio(false); cin.tie(0); using namespace std; const int N = 1e6 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-8; const double PI = acos(-1); template<class T, class S> inline void add(T &a, S b) {a += b; if(a >= mod) a -= mod;} template<class T, class S> inline void sub(T &a, S b) {a -= b; if(a < 0) a += mod;} template<class T, class S> inline bool chkmax(T &a, S b) {return a < b ? a = b, true : false;} template<class T, class S> inline bool chkmin(T &a, S b) {return a > b ? a = b, true : false;} mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); int n; int que[N], be, ed; LL dp[N]; struct Node { int x, y; LL v; bool operator < (const Node &rhs) const { return x < rhs.x; } } a[N]; LD calc(int i, int j) { return ((LD)dp[j] - dp[i]) / (a[j].x - a[i].x); } int main() { scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%d%d%lld", &a[i].x, &a[i].y, &a[i].v); a[i].v = 1LL * a[i].x * a[i].y - a[i].v; } sort(a + 1, a + 1 + n); be = 1; ed = 0; que[++ed] = 0; LL ans = 0; for(int i = 1; i <= n; i++) { int x = a[i].x, y = a[i].y; LL v = a[i].v; while(ed - be >= 1 && calc(que[be + 1], que[be]) >= y) be++; int id = que[be]; dp[i] = dp[id] + - 1LL * y * a[id].x + v; while(ed - be >= 1 && calc(que[ed], que[ed - 1]) <= calc(i, que[ed])) ed--; que[++ed] = i; chkmax(ans, dp[i]); } printf("%lld ", ans); return 0; } /* */