Submission #711941

#TimeUsernameProblemLanguageResultExecution timeMemory
711941JohannUplifting Excursion (BOI22_vault)C++14
100 / 100
1448 ms1764 KiB
#include "bits/stdc++.h"
using namespace std;

typedef long long ll;
typedef pair<ll, ll> pii;
typedef vector<pii> vpii;
typedef vector<ll> vi;
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()

vi calcShifts(ll a)
{
    vi ans;
    ll i = 0;
    while ((1LL << i) <= a)
    {
        a -= (1LL << i);
        ans.push_back(i++);
    }
    while (i > 0)
        if ((1LL << --i) <= a)
            ans.push_back(i), a -= (1 << i);
    return ans;
}

vi dp;
ll center;
void initDP(ll M, ll zero)
{
    center = M * M;
    dp.assign(2 * center + 1, INT_MIN);
    assert(0 <= center + zero && center + zero < sz(dp));
    dp[center + zero] = 0;
}
void addToDP(ll lift, ll maxNum)
{
    ll f = (maxNum < 0) ? -1 : 1;
    vi shifts = calcShifts(abs(maxNum));
    for (int i : shifts)
    {
        ll amount = f * (1 << i);
        ll d = amount * lift;
        if (d > 0)
        {
            for (int j = sz(dp) - 1; j >= d; --j)
                dp[j] = max(dp[j], (dp[j - d] != INT_MIN) ? dp[j - d] + amount : INT_MIN);
        }
        else
        {
            for (int j = 0; j < sz(dp) - abs(d); ++j)
                dp[j] = max(dp[j], (dp[j - d] != INT_MIN) ? dp[j - d] + amount : INT_MIN);
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    ll M, L;
    cin >> M >> L;
    vi A(2 * M + 1);
    for (int i = 0; i < sz(A); ++i)
        cin >> A[i];

    ll totalSum = 0;
    for (int i = 0; i < sz(A); ++i)
        totalSum += (i - M) * A[i];

    if (totalSum < L)
    {
        reverse(all(A));
        totalSum *= -1;
        L *= -1;
    }

    // find last Prefix position { i, idx } with pref <= L, or { sz(A)-1 = 2 * M, A[2 * M] }

    int i = 0;
    ll tmpans = 0, pref = 0;
    vpii toadd;
    for (; i < M; ++i)
    { // taking all negative values
        tmpans += A[i];
        pref += A[i] * (i - M);
        toadd.push_back({i - M, max(-A[i], -M)});
    }

    while (i < sz(A) && pref + A[i] * (i - M) < L)
    {
        pref += A[i] * (i - M);
        tmpans += A[i];
        toadd.push_back({i - M, max(-A[i], -M)});
        ++i;
    }
    if (i == sz(A) || L - pref < 0)
    {
        cout << "impossible\n";
        return 0;
    }

    assert(L - pref >= 0); // The expectation after the while loop is, that one is able to forfill this shit with the A[i] * (i - M) stuff
    ll l = (L - pref) / (i - M);
    pref += l * (i - M);
    tmpans += l;

    toadd.push_back({i - M, max(-l, -M)});
    toadd.push_back({i - M, min(A[i] - l, M)});
    for (int j = i + 1; j < sz(A); ++j)
        toadd.push_back({j - M, min(A[j], M)});

    initDP(M, pref - L);
    for (pii add : toadd)
        addToDP(add.first, add.second);

    ll ans = INT_MIN;
    if (dp[center] != INT_MIN)
        ans = tmpans + dp[center];

    if (ans == INT_MIN)
        cout
            << "impossible\n";
    else
        cout << ans << "\n";

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...