Pagini recente » Cod sursa (job #3141607) | Cod sursa (job #668160) | Cod sursa (job #1571703) | Cod sursa (job #2771406) | Cod sursa (job #1988255)
#include <vector>
#include <iostream>
#include <queue>
#include <set>
#include <cassert>
using namespace std;
struct FenwickTreeSet {
vector<int> fenwick;
vector<bool> exists;
int n, max_step;
FenwickTreeSet(int n) :
fenwick(n + 1, 0), exists(n, false), n(n) {
for (max_step = 1; max_step <= n; max_step *= 2);
}
int order_of_key(int pos) {
int ret = -1;
for (++pos; pos > 0; pos -= (pos & -pos))
ret += fenwick[pos];
return ret;
}
bool insert(int pos) {
if (exists[pos]) return false;
exists[pos] = true;
for (++pos; pos <= n; pos += (pos & -pos))
fenwick[pos] += 1;
return true;
}
bool erase(int pos) {
if (!exists[pos]) return false;
exists[pos] = false;
for (++pos; pos <= n; pos += (pos & -pos))
fenwick[pos] -= 1;
return true;
}
int find_by_order(int k) {
if (k < 0) return -1;
int ret = 0;
for (int step = max_step; step; step /= 2) {
if (ret + step <= n && fenwick[ret + step] <= k) {
k -= fenwick[ret + step];
ret += step;
}
}
if (ret == n)
return -1;
return ret;
}
};
template<typename T>
struct LinearFunSet {
vector<T> slopes, intercepts;
FenwickTreeSet fenwick;
int n;
LinearFunSet(vector<T> slopes) : fenwick(slopes.size()) {
sort(slopes.begin(), slopes.end());
slopes.resize(unique(slopes.begin(), slopes.end()) - slopes.begin());
this->slopes = slopes;
n = slopes.size();
intercepts.resize(n, 123456789);
}
int get_pos(int slope) {
int ret = lower_bound(slopes.begin(), slopes.end(), slope)
- slopes.begin();
assert(slopes[ret] == slope);
return ret;
}
bool is_bad(int pos) {
if (pos == -1) return false;
int order = fenwick.order_of_key(pos);
int prv = fenwick.find_by_order(order - 1);
int nxt = fenwick.find_by_order(order + 1);
if (prv == -1 or nxt == -1) return false;
long long ad = (intercepts[pos] - intercepts[prv])
* (slopes[nxt] - slopes[pos]);
long long bc = (intercepts[pos] - intercepts[nxt])
* (slopes[prv] - slopes[pos]);
return ad >= bc;
}
void check_stack(int pos) {
if (is_bad(pos)) {
assert(fenwick.erase(pos));
return;
}
while (true) {
int order = fenwick.order_of_key(pos);
int prv = fenwick.find_by_order(order - 1);
if (is_bad(prv)) {
assert(fenwick.erase(prv));
} else break;
}
while (true) {
int order = fenwick.order_of_key(pos);
int nxt = fenwick.find_by_order(order + 1);
if (is_bad(nxt)) {
assert(fenwick.erase(nxt));
} else break;
}
}
T EvaluateMax(T x) {
int step;
T best = numeric_limits<T>::min();
int at = -1;
for (step = 1; step <= n; step *= 2);
for (step /= 2; step; step /= 2) {
int fun_id = fenwick.find_by_order(at + step);
if (fun_id != -1) {
T now = slopes[fun_id] * x + intercepts[fun_id];
if (now >= best) {
best = now;
at += step;
}
}
}
return best;
}
void AddFunction(int slope, int intercept) {
int pos = get_pos(slope);
if (!fenwick.insert(pos) and intercepts[pos] >= intercept)
return;
intercepts[pos] = intercept;
check_stack(pos);
}
};
int main() {
freopen("euro.in", "r", stdin);
freopen("euro.out", "w", stdout);
int n, t;
cin >> n >> t;
vector<long long> gain(n + 1);
for (int i = 1; i <= n; ++i) {
cin >> gain[i];
gain[i] += gain[i - 1];
}
// 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
for (auto &x : gain) x = -x;
LinearFunSet<long long> linear_set(gain);
for (auto &x : gain) x = -x;
long long ans = 0;
linear_set.AddFunction(0, 0);
for (int i = 1; i <= n; ++i) {
ans = linear_set.EvaluateMax(i) + gain[i] * i - t;
linear_set.AddFunction(-gain[i], ans);
}
cout << ans << endl;
return 0;
}