Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- using ll = long long;
- bool less_than_or_equal(ll a1, ll b1, ll a2, ll b2) {
- if (a1 / b1 != a2 / b2) return a1 / b1 <= a2 / b2;
- return (a1 % b1) * b2 <= (a2 % b2) * b1;
- }
- // We messed up on messenger, the real function is:
- //
- // S[i] = A[i] - k*(i*i - 2*i + 1) + max_j ( S[j] - k*j*j - 2*k*j + 2*k*j*i )
- //
- // So a_j is INCREASING in j
- int main() {
- ll n, k;
- scanf("%lld %lld", &n, &k);
- vector<ll> A(n);
- for (ll &x : A) scanf("%lld", &x);
- ll ans = *max_element(A.begin(), A.end()); // not empty
- vector<pair<ll, ll>> V; // "active" affine functions in increasing order of first
- V.emplace_back(2*k*0, A[0] - k * 0 * 0 - 2 * k * 0); // function for j = 0
- int chico = 0; // index of the function that gave the maximum
- for (ll i = 1; i < n; i++) {
- // If chico >= V.size() it means that in the previous iteration a lot of functions were deleted
- chico = min(chico, (int)V.size() - 1);
- // the maximum is at chico or above... so advance chico while increasing
- // Note that "chico" only increases and is always < n, so this while loop will run for O(n) iterations in total.
- while (chico < V.size() - 1 && V[chico].first * i + V[chico].second < V[chico + 1].first * i + V[chico + 1].second)
- chico++;
- // Compute S
- ll S = max(A[i], A[i] - k * (i*i - 2*i + 1) + V[chico].first * i + V[chico].second);
- ans = max(ans, S);
- // Insert the new function at V. It has the smallest first, so it will be there.
- ll a = 2*k*i;
- ll b = S - k*i*i - 2*k*i;
- // First pop all functions that become inactive.
- // Note that every function will be popped at most once, so this while loop has at most O(n) iterations.
- while (V.size() >= 2) {
- // if the intersection between the new function and V[V.size() - 2] comes before
- // the intersection between the two last two functions than V[V.size() - 1] becomes inactive.
- //
- // Chico, draw this :)
- // intersection between a1*x + b1 and a2 * x + b2 happens at (b2 - b1) / (a1 - a2) (note that a1 != a2)
- if (less_than_or_equal(
- V[V.size() - 2].second - b, a - V[V.size() - 2].first, // fraction that represents where new function and V[V.size() - 2] intersect
- V[V.size() - 2].second - V.back().second, V.back().first - V[V.size() - 2].first) // where last two functions intersect
- ) V.pop_back();
- else break;
- }
- // insert the new one
- V.emplace_back(a, b);
- }
- printf("%lld\n", ans);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement