Submission #390166

#TimeUsernameProblemLanguageResultExecution timeMemory
390166ronnithBuilding Bridges (CEOI17_building)C++14
100 / 100
61 ms8212 KiB
#include <bits/stdc++.h>

using namespace std;

struct line {
	long long m, c;
	line() : m(0), c(0) {}
	line(long long mm, long long cc) : m(mm), c(cc) {}
	inline long long get_y(long long x) { return m*x+c; }
};

void swap(line& x, line& y) {
	swap(x.m, y.m);
	swap(x.c, y.c);
}

struct node {
	int l, r;
	line crr;
	node* left;
	node* right;
	node(int ll, int rr) : l(ll), r(rr), left(nullptr), right(nullptr) {}
	node(int ll, int rr, line L) : l(ll), r(rr), crr(L), left(nullptr), right(nullptr) {}
};

struct li_chao_tree {
	int MX;
	node* root;

	li_chao_tree(int _) : MX(_) {
		root = nullptr;
	}

	inline bool is_mid_range(int l, int r, node* v, line L) {
		return (v->crr.get_y(l) > L.get_y(l)) != (v->crr.get_y(r) > L.get_y(r));
	}

	void insert(node* v, int lx, int rx, line L) {
		if(lx == rx) {
			if(L.get_y(lx) < v->crr.get_y(lx)) {
				v->crr = L;
			}
		} else {
			int mid = (lx+rx)/2;
			if(is_mid_range(lx, mid, v, L)) {
				if(v->crr.get_y(rx) > L.get_y(rx)) {
					swap(v->crr, L);
				}
				if(v->left == nullptr) {
					v->left = new node(lx, mid, L);
					return;
				}
				insert(v->left, lx, mid, L);
			} else {
				if(v->crr.get_y(lx) > L.get_y(lx)) {
					swap(v->crr, L);
				}
				if(v->right == nullptr) {
					v->right = new node(mid + 1, rx, L);
					return;
				}
				insert(v->right, mid + 1, rx, L);
			}
		}
	}

	void insert(line L) {
		if(root == nullptr) {
			root = new node(0, MX, L);
			return;
		}
		insert(root, 0, MX, L);
	}

	long long query(node* v, int x) {
		if(v == nullptr) return LONG_LONG_MAX;
		int mid = (v->l+v->r)/2;
		if(x <= mid) {
			return min(query(v->left, x), v->crr.get_y(x));
		} else {
			return min(query(v->right, x), v->crr.get_y(x));
		}
	}
	
	long long query(int x) {
		return query(root, x);
	}
};

const int N = (int)1e5;
const int MX = (int)1e6;
int n;
long long H[N], W[N], dp[N];

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cin >> n;
	for(int i = 0;i < n;i ++) {
		cin >> H[i];
	}
	for(int i = 0;i < n;i ++) {
		cin >> W[i];
		if(i != 0) W[i] += W[i - 1];
	}
	dp[0] = 0;
	li_chao_tree lct(MX);
	lct.insert(line(-2*H[0], H[0]*H[0]-W[0]+dp[0]));
	for(int i = 1;i < n;i ++) {
		dp[i] = H[i]*H[i]+W[i-1] + lct.query(H[i]);
		lct.insert(line(-2*H[i], H[i]*H[i]-W[i]+dp[i]));
	}
	cout << dp[n - 1] << '\n';
	return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...