Advertisement
Guest User

Untitled

a guest
Oct 23rd, 2017
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.54 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. using ll = long long;
  5.  
  6. bool less_than_or_equal(ll a1, ll b1, ll a2, ll b2) {
  7.   if (a1 / b1 != a2 / b2) return a1 / b1 <= a2 / b2;
  8.   return (a1 % b1) * b2 <= (a2 % b2) * b1;
  9. }
  10.  
  11. // We messed up on messenger, the real function is:
  12. //
  13. // S[i] = A[i] - k*(i*i - 2*i + 1) + max_j ( S[j] - k*j*j - 2*k*j + 2*k*j*i )
  14. //
  15. //  So a_j is INCREASING in j
  16. int main() {
  17.   ll n, k;
  18.   scanf("%lld %lld", &n, &k);
  19.   vector<ll> A(n);
  20.   for (ll &x : A) scanf("%lld", &x);
  21.   ll ans = *max_element(A.begin(), A.end()); // not empty
  22.  
  23.   vector<pair<ll, ll>> V; // "active" affine functions in increasing order of first
  24.  
  25.   V.emplace_back(2*k*0, A[0] - k * 0 * 0 - 2 * k * 0); // function for j = 0
  26.   int chico = 0; // index of the function that gave the maximum
  27.  
  28.   for (ll i = 1; i < n; i++) {
  29.     // If chico >= V.size() it means that in the previous iteration a lot of functions were deleted
  30.     chico = min(chico, (int)V.size() - 1);
  31.  
  32.     // the maximum is at chico or above... so advance chico while increasing
  33.     // Note that "chico" only increases and is always < n, so this while loop will run for O(n) iterations in total.
  34.     while (chico < V.size() - 1 && V[chico].first * i + V[chico].second < V[chico + 1].first * i + V[chico + 1].second)
  35.       chico++;
  36.  
  37.     // Compute S
  38.     ll S = max(A[i], A[i] - k * (i*i - 2*i + 1) + V[chico].first * i + V[chico].second);
  39.     ans = max(ans, S);
  40.  
  41.     // Insert the new function at V. It has the smallest first, so it will be there.
  42.     ll a = 2*k*i;
  43.     ll b = S - k*i*i - 2*k*i;
  44.  
  45.     // First pop all functions that become inactive.
  46.     // Note that every function will be popped at most once, so this while loop has at most O(n) iterations.
  47.     while (V.size() >= 2) {
  48.       // if the intersection between the new function and V[V.size() - 2] comes before
  49.       //   the intersection between the two last two functions than V[V.size() - 1] becomes inactive.
  50.       //
  51.       // Chico, draw this :)
  52.  
  53.       // intersection between a1*x + b1 and a2 * x + b2 happens at (b2 - b1) / (a1 - a2) (note that a1 != a2)
  54.       if (less_than_or_equal(
  55.             V[V.size() - 2].second - b, a - V[V.size() - 2].first, // fraction that represents where new function and V[V.size() - 2] intersect
  56.             V[V.size() - 2].second - V.back().second, V.back().first - V[V.size() - 2].first) // where last two functions intersect
  57.          ) V.pop_back();
  58.       else break;
  59.     }
  60.     // insert the new one
  61.     V.emplace_back(a, b);
  62.   }
  63.   printf("%lld\n", ans);
  64.   return 0;
  65. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement