Tutorial for Codeforces 1358E - Are You Fired?

Solutions

Solution #

First, let’s define the function fk(i)=ai+ai+1+⋯+ai+k−1f_k(i)=a_i+a_{i+1}+\dots +a_{i+k-1}, i.e. the sum of kk consecutive months starting at ii.

Now, let’s prove that if kk is one answer and k≤n2k\leq \dfrac n 2, then 2⋅k2\cdot k is also an answer: f2k(i)=fk(i)+fk(i+k)>0f_{2k}(i)=f_k(i)+f_k(i+k)>0. Thus we can always find an answer greater than n2\dfrac n 2.

Then, consider the case where x≥0x\ge 0. If kk is an answer, since fk+1(i)=fk(i)+ai+1=fk(i)+x>0f_{k+1}(i)=f_k(i)+a_{i+1}=f_k(i)+x>0, k+1k+1 is also an answer. Thus it’s sufficient to check if k=nk=n is the answer.

Lastly, when x<0x<0, we need the help of the prefix sum. Define prei=a0+a1+⋯+ai−1,i>0pre_i=a_0+a_1+\dots+a_{i-1},i>0 and pre0=0pre_0=0. We want to find a kk such that for each 0≤i≤n−k0\leq i\leq n-k, we have:

prei+k−prei>0 prei<prei+k\begin{aligned}pre_{i+k}-pre_i&>0 \\\ pre_{i}&< pre_{i+k}\end{aligned}

Since k>n2k>\dfrac n 2, the numbers after the window must be xx, so the formula can be rewrite as:

prei<pren−x⋅(n−k−i) prei+x⋅(n−i)<pren+x⋅k\begin{align*}pre _i& < pre _n-x\cdot(n-k-i) \\\ pre_i+x\cdot(n-i)&< pre _n+x\cdot k\end{align*}

For each ii, the corresponding kk is n−in-i, this means if the max value of the LHS is smaller than pren+x⋅(n−i)pre_n+x\cdot (n-i), then k=n−ik=n-i is a answer.

Code #

#include <bits/stdc++.h>
 
#define forn(i, n) for (int i = 0; i < int(n); ++i)
#define all(x) (x).begin(), (x).end()
 
using namespace std;
using ll = long long;
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    vector<ll> a(n);
    forn(i, (n + 1) / 2) {
        cin >> a[i];
    }
    int x;
    cin >> x;
    for (int i = (n + 1) / 2; i < n; i++) a[i] = x;
    vector<ll> ps(n + 1);
    partial_sum(all(a), ps.begin() + 1);
    if (ps.back() > 0) return cout << n, 0;
    if (x >= 0) return cout << -1, 0;
    ll N2 = n / 2, N1 = n - N2, sum = ps.back();
    ll mx = -1e18;
    for (int i = 0; i <= N1; i++) {
        mx = max(mx, ps[i] + x * ll(n - i));
        if (mx < sum + x * ll(n - i)) {
            cout << n - i;
            return 0;
        }
    }
    cout << -1;
    return 0;
}