Submission #624724

#TimeUsernameProblemLanguageResultExecution timeMemory
624724JomnoiBuilding Bridges (CEOI17_building)C++17
100 / 100
67 ms9688 KiB
#include <bits/stdc++.h>
using namespace std;

const int MAX_N = 1e5 + 5;
const long long INF = 1e18 + 7;

bool queryMode;
long long H[MAX_N], W[MAX_N];
long long dp[MAX_N];

long long divide(long long a, long long b) {
    return a / b - (a % b != 0 and (a ^ b) < 0);
}

struct Line {
    mutable long long m, c, p;

    Line() {}
    Line(long long m_, long long c_) : m(m_), c(c_), p(0) {}
    Line(long long m_, long long c_, long long p_) : m(m_), c(c_), p(p_) {}

    bool operator<(const Line &o) const {
        if(queryMode == true) {
            return p < o.p;
        }
        return m < o.m;
    }
};

struct LineContainer : multiset <Line> {
    bool intersect(iterator now, iterator nxt) {
        if(nxt == end()) {
            now->p = INF;
            return false;
        }
        if(now->m == nxt->m) {
            now->p = -INF;
            if(now->c > nxt->c) {
                now->p = INF;
            }
        }
        else {
            now->p = divide(now->c - nxt->c, nxt->m - now->m);
        }
        return now->p >= nxt->p;
    }

    void addLine(Line f) {
        auto nxt = insert(f), now = nxt++, prv = now;
        while(intersect(now, nxt) == true) {
            nxt = erase(nxt);
        }
        if(prv != begin() and intersect(--prv, now) == true) {
            intersect(prv, now = erase(now));
        }
        while((now = prv) != begin() and (--prv)->p >= now->p) {
            intersect(prv, erase(now));
        }
    }

    long long query(long long x) {
        queryMode = true;
        auto it = lower_bound({-INF, -INF, x});
        queryMode = false;

        return it->m * x + it->c;
    }
};

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);

    int N;
    cin >> N;

    long long sumW = 0;
    for(int i = 1; i <= N; i++) {
        cin >> H[i];
    }
    for(int i = 1; i <= N; i++) {
        cin >> W[i];

        sumW += W[i];
    }

    LineContainer cht;
    dp[1] = -W[1];
    cht.addLine({2 * H[1], -H[1] * H[1] - dp[1]});
    for(int i = 2; i <= N; i++) {
        dp[i] = -cht.query(H[i]) + H[i] * H[i] - W[i];
        cht.addLine({2 * H[i], -H[i] * H[i] - dp[i]});
    }
    cout << sumW + dp[N];
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...