Submission #1296397

#TimeUsernameProblemLanguageResultExecution timeMemory
1296397chaitanyamehtaFeast (NOI19_feast)C++20
0 / 100
65 ms2764 KiB
#include <bits/stdc++.h>
using namespace std;

#define int long long
using i128 = __int128_t;

int n, k;
const int NEG_INF = LLONG_MIN / 4;
vector<int> a;

inline pair<int,int> better(const pair<int,int> &A, const pair<int,int> &B) {
    if (A.first != B.first) return (A.first > B.first) ? A : B;
    return (A.second >= B.second) ? A : B; // tie: prefer larger count
}

// Evaluate one lambda (penalty). Returns {best_adjusted_value, segments_used}
pair<int,int> eval_lambda(int lambda) {
    pair<int,int> dp0 = {0, 0};          // best up to i (maybe not ending at i)
    pair<int,int> dp1 = {NEG_INF, 0};    // best with a segment that ends exactly at i

    for (int i = 0; i < n; ++i) {
        pair<int,int> extend = { (dp1.first == NEG_INF ? NEG_INF : dp1.first + a[i]), dp1.second };
        pair<int,int> start  = { dp0.first + a[i] - lambda, dp0.second + 1 };
        dp1 = better(extend, start);
        dp0 = better(dp0, dp1);
    }
    return dp0;
}

int solve_lambda() {
    // Use safe, tight bounds derived from input to avoid overflow
    // sumAbs = sum |a[i]| <= n * 1e9 <= 3e14 (within 64-bit safely)
    long long sumAbs = 0;
    for (int i = 0; i < n; ++i) sumAbs += llabs(a[i]);
    int L = (int)(-sumAbs - 5);
    int R = (int)( sumAbs + 5);

    while (L < R) {
        int mid = L + ( (R - L + 1) >> 1 ); // upper-mid
        if (eval_lambda(mid).second >= k) L = mid;
        else R = mid - 1;
    }
    return L;
}

string toString128(i128 x) {
    if (x == 0) return "0";
    bool neg = x < 0;
    if (neg) x = -x;
    string s;
    while (x > 0) {
        int d = (int)(x % 10);
        s.push_back(char('0' + d));
        x /= 10;
    }
    if (neg) s.push_back('-');
    reverse(s.begin(), s.end());
    return s;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    if (!(cin >> n >> k)) return 0;
    a.assign(n, 0);
    for (int i = 0; i < n; ++i) cin >> a[i];

    // 1) find lambda boundary
    int bestLambda = solve_lambda();

    // 2) evaluate a few nearby lambdas to be robust against tie/boundary issues
    auto pL   = eval_lambda(bestLambda);
    auto pLm1 = eval_lambda(bestLambda - 1);
    // also check bestLambda+1 (optional, cheap)
    auto pLp1 = eval_lambda(bestLambda + 1);

    // 3) from each evaluation we can build a candidate answer for exactly K segments:
    // answer_candidate = adjusted_value + lambda * K
    // Note: adjusted_value = best( f(x) - lambda*x ) = f(c) - lambda*c  for the chosen c
    // And candidate = (f(c) - lambda*c) + lambda*K = f(c) + lambda*(K - c).
    // This is a valid candidate (possibly not the true maximum for exactly K), 
    // but checking neighbors covers boundary/tie cases.
    i128 cand1 = (i128)pL.first   + (i128)bestLambda * (i128)k;
    i128 cand2 = (i128)pLm1.first + (i128)(bestLambda - 1) * (i128)k;
    i128 cand3 = (i128)pLp1.first + (i128)(bestLambda + 1) * (i128)k;

    // 4) final answer is max among candidates and 0 (empty segments allowed)
    i128 ans128 = cand1;
    if (cand2 > ans128) ans128 = cand2;
    if (cand3 > ans128) ans128 = cand3;
    if (ans128 < 0) ans128 = 0;

    cout << toString128(ans128) << '\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...