#include <iostream>
#include <vector>
#include <climits>
using namespace std;
 
typedef long long ll;
 
// Structure representing a line of the form f(x)= m*x + b.
struct Line {
    ll m, b;
    Line(ll _m = 0, ll _b = LLONG_MAX) : m(_m), b(_b) {}
    ll eval(ll x) const {
        return m * x + b;
    }
};
 
// LiChao tree implementation to maintain a set of lines and answer minimum queries.
struct LiChao {
    struct Node {
        Line line;
        Node *l, *r;
        Node(Line line): line(line), l(nullptr), r(nullptr) {}
    };
    
    Node* root;
    ll L, R;
    
    // The tree covers x in [L, R)
    LiChao(ll l, ll r) : L(l), R(r) {
        root = new Node(Line(0, LLONG_MAX)); // initial dummy line with "infinite" cost.
    }
    
    // Add a new line to the structure.
    void addLine(Line newline) {
        addLine(root, L, R, newline);
    }
    
    void addLine(Node* node, ll l, ll r, Line newline) {
        ll mid = (l + r) >> 1;
        bool left = newline.eval(l) < node->line.eval(l);
        bool mVal = newline.eval(mid) < node->line.eval(mid);
        if(mVal) {
            // Swap the lines.
            Line temp = node->line;
            node->line = newline;
            newline = temp;
        }
        if(r - l == 1) return; // reached a leaf interval.
        if(left != mVal) {
            if(!node->l) node->l = new Node(Line(0, LLONG_MAX));
            addLine(node->l, l, mid, newline);
        } else {
            if(!node->r) node->r = new Node(Line(0, LLONG_MAX));
            addLine(node->r, mid, r, newline);
        }
    }
    
    // Query the minimum value at point x.
    ll query(ll x) {
        return query(root, L, R, x);
    }
    
    ll query(Node* node, ll l, ll r, ll x) {
        if(!node) return LLONG_MAX;
        ll mid = (l + r) >> 1;
        ll cur = node->line.eval(x);
        if(r - l == 1) return cur;
        if(x < mid)
            return min(cur, query(node->l, l, mid, x));
        else
            return min(cur, query(node->r, mid, r, x));
    }
};
 
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n; 
    cin >> n;
    vector<ll> h(n+1), w(n+1);
    for (int i = 1; i <= n; i++){
        cin >> h[i];
    }
    for (int i = 1; i <= n; i++){
        cin >> w[i];
    }
    
    // Precompute prefix sums of removal costs.
    vector<ll> pref(n+1, 0);
    for (int i = 1; i <= n; i++){
        pref[i] = pref[i-1] + w[i];
    }
    
    // dp[i]: minimum cost to build a valid bridge ending at pillar i.
    vector<ll> dp(n+1, 0);
    dp[1] = 0; // starting at the first pillar.
    
    // LiChao tree for x in [0, 1e6+1). Since 0 <= h[i] <= 1e6.
    ll Xlow = 0, Xhigh = 1000001;
    LiChao tree(Xlow, Xhigh);
    
    // For the first pillar, add the corresponding line:
    // slope = -2*h[1], intercept = dp[1] - pref[1] + h[1]^2.
    tree.addLine(Line(-2LL * h[1], dp[1] - pref[1] + h[1]*h[1]));
    
    for (int i = 2; i <= n; i++){
        // Query the minimum value at x = h[i].
        ll best = tree.query(h[i]);
        // Compute dp[i] using the recurrence.
        dp[i] = pref[i-1] + h[i]*h[i] + best;
        // Add the line corresponding to pillar i.
        tree.addLine(Line(-2LL * h[i], dp[i] - pref[i] + h[i]*h[i]));
    }
    
    cout << dp[n] << "\n";
    return 0;
}
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... |