Cod sursa(job #2156661)

Utilizator retrogradLucian Bicsi retrograd Data 8 martie 2018 21:48:10
Problema Euro Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.74 kb
#include <bits/stdc++.h>

using namespace std;


using T = long long;

bool QUERY;
struct Line {
	mutable T a, b, p;
    T Eval(T x) const { return a * x + b; }
	bool operator<(const Line& o) const {
		return QUERY ? p < o.p : a < o.a;
	}
};

struct LineContainer : multiset<Line> {
	// for doubles, use kInf = 1/.0, div(a, b) = a / b
	const T kInf = numeric_limits<T>::max();
	T div(T a, T b) { // floored division
		return a / b - ((a ^ b) < 0 && a % b); }
	bool isect(iterator x, iterator y) {
		if (y == end()) { x->p = kInf; return false; }
		if (x->a == y->a) x->p = x->b > y->b ? kInf : -kInf;
		else x->p = div(y->b - x->b, x->a - y->a);
		return x->p >= y->p;
	}
	void InsertLine(T a, T b) {
		auto nx = insert({a, b, 0}), it = nx++, pv = it;
		while (isect(it, nx)) nx = erase(nx);
		if (pv != begin() && isect(--pv, it)) isect(pv, it = erase(it));
		while ((it = pv) != begin() && (--pv)->p >= it->p)
			isect(pv, erase(it));
	}
	T EvalMax(T x) {
		assert(!empty());
		QUERY = 1; auto it = lower_bound({0,0,x}); QUERY = 0;
		return it->Eval(x);
	}
};

int main() {
    freopen("euro.in", "r", stdin);
    freopen("euro.out", "w", stdout);
       
    int n, t;
    cin >> n >> t;
 
    // dp[i] = max_j(dp[j] + (gain[i] - gain[j]) * i - t)
    // dp[i] = max_j(dp[j] - gain[j] * i + gain[i] * i - t)
    // dp[i] = gain[i] * i - t + max_j(dp[j] - gain[j] * i)
    // solution: keep stack of linear functions of type
    //           -gain[j] * X + dp[j]
    // no monotony -> need set
   
    LineContainer ct;
    ct.InsertLine(0, 0);
   
    long long ans = 0, gain = 0;
    for (int i = 1; i <= n; ++i) {
        int x; cin >> x; gain += x;
        ans = ct.EvalMax(i) + gain * i - t;
        ct.InsertLine(-gain, ans);
    }
    cout << ans << endl;
    return 0;
}