제출 #598751

#제출 시각아이디문제언어결과실행 시간메모리
598751devedudeBuilding Bridges (CEOI17_building)C++17
100 / 100
52 ms9700 KiB
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef tuple<int, int> ii;
typedef tuple<int, int, int> iii;
typedef vector<int> vi;

#define FOR(i, a, b) for (int i = (a); i < (b); ++i)

const ll inf = LLONG_MAX;

void run();

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    run();
}

inline ll sqr(ll x) {
    return x * x;
}

struct Line {
    ll a, b;
    mutable ll max_x;
    bool operator<(const Line &o) const {
        return a > o.a;
    }
    bool operator<(ll x) const {
        return max_x < x;
    }
};

struct LineContainer : multiset<Line, less<>> {
    ll div(ll n, ll d) { // floor division for negative and positive lls
        return n / d - ((n ^ d) < 0 && n % d);
    }
    bool isect(iterator l, iterator m) {
        // assumption: l and m are neighbouring lines, with m > l
        // do: adjust the max_x for l
        // return: l covers x after or equal to last x of m
        if (m == end()) { // handle case l is last line
            l->max_x = inf;
            return false;
        }
        if (l->a == m->a) { // prevent division by zero
            l->max_x = l->b < m->b ? inf : -inf;
        } else { // default case, intersection point of l and m floored
            l->max_x = div(m->b - l->b, l->a - m->a);
        }
        return l->max_x >= m->max_x;
    }
    void add(ll a, ll b) {
        auto cur = insert({a, b, 0}), pre = cur, nex = cur; // iterators
        //cerr << "Adding line " << cur->a << ' ' << cur->b << ' ';
        ++nex;
        while (isect(cur, nex)) nex = erase(nex); // keep erasing redundant lines after cur, note how this sets max_x of cur
        //cerr << cur->max_x << '\n';
        if (cur != begin() && isect(--pre, cur)) { // added line itself is redundant, erase and return
            cur = erase(cur);
            isect(pre, cur);
        }
        while ((cur = pre) != begin() && (--pre)->max_x >= cur->max_x) isect(pre, erase(cur)); // keep erasing redundant lines before cur, and adjust max_x of line left
    }
    ll min_y(ll x) {
        auto l = lower_bound(x);
        //cerr << "Minimal for x = " << x << " is line a = " << l->a << " b = " << l->b << " at y = " << l->y(x) << '\n';
        return l->a * x + l->b;
    }
};

int N;
ll h[100005];
ll W[100005];
ll dp[100005];

void run() {
    cin >> N;
    FOR(i, 0, N) cin >> h[i];
    FOR(i, 0, N) {
        ll w; cin >> w;
        W[i+1] = W[i] + w;
    }
    LineContainer lc;
    FOR(i, 1, N) {
        lc.add(-2*h[i-1], dp[i-1] + h[i-1]*h[i-1] - W[i]);
        dp[i] = h[i]*h[i] + W[i] + lc.min_y(h[i]);
    }
    // for (auto &l : lc) {
    //     cerr << l.a << ' ' << l.b << ' ' << l.max_x << '\n';
    // }
    cout << dp[N-1] << '\n';
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...