Submission #401348

#TimeUsernameProblemLanguageResultExecution timeMemory
401348gmyuBuilding Bridges (CEOI17_building)C++14
100 / 100
62 ms10452 KiB
/*
ID: USACO_template
LANG: C++
PROG: https://oj.uz/problem/view/CEOI17_building
*/
#include <iostream>  //cin , cout
#include <fstream>   //fin, fout
#include <stdio.h>   // scanf , pringf
#include <cstdio>
#include <algorithm> // sort , stuff
#include <stack>     // stacks
#include <queue>     // queues
#include <map>
#include <string>
#include <string.h>
#include <set>

using namespace std;

typedef pair<int, int>          pii;
typedef vector<int>             vi;     /// adjlist without weight
typedef vector<pii>             vii;    /// adjlist with weight
typedef vector<pair<int,pii>>   vpip;   /// edge with weight
typedef long long               ll;

#define mp  make_pair
#define ff  first
#define ss  second
#define pb  push_back
#define sz(x)   (int)(x).size()
#define adjread {int a, b; cin >> a >> b; adjlist[a].pb(b); adjlist[b].pb(a); }

const int MOD = 1e9+7;  // 998244353;
const int MX  = 2e5+5;   //
const ll  INF = 1e18;    //

#define MAXV 100007
#define MAXE 100007


bool debug;

int N;
ll h[MAXV], w[MAXV], psw[MAXV];
ll dp[MAXV];

/**
 * Author: Simon Lindholm
 * Date: 2017-04-20
 * License: CC0
 * Source: own work
 * Description: Container where you can add lines of the form kx+m, and query maximum values at points x.
 *  lower convext hull
 *  Useful for dynamic programming (``convex hull trick'').
 * Time: O(\log N)
 * Status: stress-tested
 * https://github.com/kth-competitive-programming/kactl/blob/main/content/data-structures/LineContainer.h
 * usage example: https://oj.uz/submission/237141
 */
#include <assert.h>     /* assert */

int lc_comp_type = 1;
struct Line {
    /// y = kx + m; p is the intersection point of line y and the next line on the convex hull
	mutable ll k, m, p;     // can add additional info such as id
	bool operator<(const Line& o) const {
	    if(lc_comp_type == 1) {
            return k < o.k;
	    } else {
	        return p < o.p;
	    }
    }
	//bool operator<(const ll& x) const { return p < x; }
};

struct LineContainer {
    multiset<Line> hull;
    int hull_type = 1;  /// 1 for max val (lower convex hull), -1 for min val (upper convex hull)
	// (for doubles, use inf = 1/.0, div(a,b) = a/b)
	static const ll lc_inf = 1LL << 62;
	ll div(ll a, ll b) { // floored division
		return a / b - ((a ^ b) < 0 && a % b); }
	bool isect(multiset<Line>::iterator x, multiset<Line>::iterator y) {
		if (y == hull.end()) { x->p = lc_inf; return false; }
		if (x->k == y->k) x->p = (x->m > y->m) ? lc_inf : -lc_inf;
		else x->p = div(y->m - x->m, x->k - y->k);      // p is the intersect against next line
		return x->p >= y->p;
	}
	void add(ll k, ll m) {
	    /// if, instead of max val (lower convex hull), we need min val (upper convex hull), we flip the hull
	    k *= (ll)hull_type; m *= (ll)hull_type;
		auto z = hull.insert({k, m, 0}), y = z, x = y;
		z++;
		while (isect(y, z)) z = hull.erase(z);
		if (x != hull.begin() && isect(--x, y)) isect(x, y = hull.erase(y));
		while ((y = x) != hull.begin() && (--x)->p >= y->p)
			isect(x, hull.erase(y));
	}
	ll query(ll x) {
		assert(!hull.empty());
		Line ql; ql.p = x;
		lc_comp_type = 2;
		auto l = *hull.lower_bound(ql);
		lc_comp_type = 1;
		return (l.k * x + l.m) * (ll)hull_type;
	}
};

Line l;
LineContainer lc;

int main() {
    debug = false;
    ios_base::sync_with_stdio(false); cin.tie(0);

    cin >> N ;
    for(int i=1;i<=N;i++) {
        cin >> h[i];
    }
    for(int i=1;i<=N;i++) {
        cin >> w[i];
        psw[i] = psw[i-1] + w[i];
    }

    lc.hull_type = -1;
    dp[1] = 0;
    lc.add(-2LL*h[1], dp[1]-psw[1]+h[1]*h[1]);

    for(int i=2;i<=N;i++) {
        dp[i] = lc.query(h[i]) + h[i] * h[i] + psw[i-1];
        if(debug) cout << dp[i] << endl;
        lc.add(-2LL*h[i], dp[i]-psw[i]+h[i]*h[i]);
    }
    cout << dp[N] << endl;


    if(debug) cout << endl << "EOL" << endl;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...