Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <cstring>
- #include <string>
- #include <vector>
- #include <map>
- #include <set>
- #include <unordered_map>
- #include <unordered_set>
- #include <algorithm>
- #include <queue>
- #include <cmath>
- #include <stdio.h>
- #define _ << " " <<
- #define debug(x) #x << " = " << x
- #define ll long long
- #define ull unsigned long long
- #define int ll
- #define float double
- using namespace std;
- struct line {
- ll m, b;
- };
- struct point {
- double x, y;
- };
- class hullt {
- struct line {
- ll m, b, val;
- double xlo;
- bool is_query;
- bool query_max;
- line(ll m, ll b, double val,
- bool is_query, bool query_max) {
- this->m = m;
- this->b = b;
- this->val = val;
- this->xlo = -std::numeric_limits<double>::max();
- this->is_query = is_query;
- this->query_max = query_max;
- }
- bool parallel(const line &l) const {
- return m == l.m;
- }
- double intersect(const line &l) const {
- if (parallel(l))
- return std::numeric_limits<double>::max();
- return (double)(l.b - b)/(m - l.m);
- }
- bool operator<(const line &l) const {
- if (l.is_query)
- return query_max ? (xlo < l.val) : (l.val < xlo);
- return m < l.m;
- }
- };
- std::set<line> hull;
- bool query_max;
- typedef std::set<line>::iterator hulliter;
- bool has_prev(hulliter it) const {
- return it != hull.begin();
- }
- bool has_next(hulliter it) const {
- return (it != hull.end()) && (++it != hull.end());
- }
- bool irrelevant(hulliter it) const {
- if (!has_prev(it) || !has_next(it))
- return false;
- hulliter prev = it, next = it;
- --prev;
- ++next;
- return query_max ? prev->intersect(*next) <= prev->intersect(*it)
- : next->intersect(*prev) <= next->intersect(*it);
- }
- hulliter update_left_border(hulliter it) {
- if ((query_max && !has_prev(it)) || (!query_max && !has_next(it)))
- return it;
- hulliter it2 = it;
- double val = it->intersect(query_max ? *--it2 : *++it2);
- line l(*it);
- l.xlo = val;
- hull.erase(it++);
- return hull.insert(it, l);
- }
- public:
- hullt(bool query_max = false) {
- this->query_max = query_max;
- }
- void add_line(ll m, ll b) {
- line l(m, b, 0, false, query_max);
- hulliter it = hull.lower_bound(l);
- if (it != hull.end() && it->parallel(l)) {
- if ((query_max && it->b < b) || (!query_max && b < it->b))
- hull.erase(it++);
- else
- return;
- }
- it = hull.insert(it, l);
- if (irrelevant(it)) {
- hull.erase(it);
- return;
- }
- while (has_prev(it) && irrelevant(--it))
- hull.erase(it++);
- while (has_next(it) && irrelevant(++it))
- hull.erase(it--);
- it = update_left_border(it);
- if (has_prev(it))
- update_left_border(--it);
- if (has_next(++it))
- update_left_border(++it);
- }
- ll get_best(ll x) const {
- line q(0, 0, x, true, query_max);
- hulliter it = hull.lower_bound(q);
- if (query_max)
- --it;
- return it->m*x + it->b;
- }
- };
- hullt hull(false);
- const int maxn = 1e6+10;
- int d[maxn], prep[maxn], t[maxn];
- int dp[maxn];
- #undef int
- int main() {
- #define int ll
- std::ios::sync_with_stdio(false);
- int n;
- scanf("%lld", &n);
- for (int i =0; i < n; i++) scanf("%lld %lld %lld", d + i, prep + i, t + i);
- int dist = d[0];
- //dp[k] + p[k] + (d[i] - d[k]) * t[k]
- /* dp[i] = min(dp[k] + b[k] * a[i]) */
- dp[0] = 0;
- line k;
- k.m = t[0];
- k.b = prep[0];
- hull.add_line(k.m, k.b);
- for (int i = 1; i < n; i++) {
- dp[i] = hull.get_best(dist - d[i]);
- // std::cout << debug(i) _ debug(dp[i]) << std::endl;
- k.m = t[i];
- k.b = dp[i] + prep[i] - (dist - d[i]) * t[i];
- hull.add_line(k.m, k.b);
- }
- printf("%lld\n", hull.get_best(dist));
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement