Submission #1300224

#TimeUsernameProblemLanguageResultExecution timeMemory
1300224danglayloi1Feast (NOI19_feast)C++20
100 / 100
177 ms135404 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

struct Node {
    ll sm = 0;
    ll pre = 0, suf = 0, res = 0;
    int l = 0, r = 0;
    int pr = -1, sf = -1; // prefix right idx, suffix left idx
    int rl = -1, rr = -1; // best subarray [rl,rr]
};

vector<Node> mx, mn;
vector<char> lz;
vector<ll> a;

Node make_leaf(ll val, int idx) {
    Node X;
    X.sm = val; X.l = X.r = idx;
    if (val > 0) {
        X.pre = X.suf = X.res = val;
        X.pr = X.sf = X.rl = X.rr = idx;
    } else {
        X.pre = X.suf = X.res = 0;
        X.pr = X.sf = X.rl = X.rr = -1;
    }
    return X;
}

Node mergeN(const Node &L, const Node &R) {
    Node P;
    P.sm = L.sm + R.sm;
    P.l = L.l; P.r = R.r;

    // prefix: choose between L.pre (idx L.pr) and L.sm + R.pre (idx R.pr)
    ll cand_pre_val = 0; int cand_pre_idx = -1;
    if (L.pr != -1) { cand_pre_val = L.pre; cand_pre_idx = L.pr; }
    // second candidate
    if (R.pr != -1) {
        ll v2 = L.sm + R.pre;
        if (v2 > cand_pre_val) { cand_pre_val = v2; cand_pre_idx = R.pr; }
    }
    P.pre = cand_pre_val; P.pr = cand_pre_idx;

    // suffix: choose between R.suf (idx R.sf) and L.suf + R.sm (idx L.sf)
    ll cand_suf_val = 0; int cand_suf_idx = -1;
    if (R.sf != -1) { cand_suf_val = R.suf; cand_suf_idx = R.sf; }
    if (L.sf != -1) {
        ll v2 = L.suf + R.sm;
        if (v2 > cand_suf_val) { cand_suf_val = v2; cand_suf_idx = L.sf; }
    }
    P.suf = cand_suf_val; P.sf = cand_suf_idx;

    // res: three candidates: L.res (L.rl), R.res (R.rl), cross (L.suf + R.pre) if both sides valid
    P.res = 0; P.rl = P.rr = -1;
    if (L.rl != -1) { P.res = L.res; P.rl = L.rl; P.rr = L.rr; }
    if (R.rl != -1 && R.res > P.res) { P.res = R.res; P.rl = R.rl; P.rr = R.rr; }
    if (L.sf != -1 && R.pr != -1) {
        ll cross = L.suf + R.pre;
        if (cross > P.res) {
            P.res = cross; P.rl = L.sf; P.rr = R.pr;
        }
    }
    // If none positive, P.res stays 0 and rl=-1
    return P;
}

void build(int nd, int l, int r) {
    if (l == r) {
        mx[nd] = make_leaf(a[l], l);
        mn[nd] = make_leaf(-a[l], l);
        return;
    }
    int mid = (l + r) >> 1;
    build(nd<<1, l, mid);
    build(nd<<1|1, mid+1, r);
    mx[nd] = mergeN(mx[nd<<1], mx[nd<<1|1]);
    mn[nd] = mergeN(mn[nd<<1], mn[nd<<1|1]);
}

void push(int nd, int l, int r) {
    if (!lz[nd]) return;
    swap(mx[nd], mn[nd]);
    if (l != r) {
        lz[nd<<1] ^= 1;
        lz[nd<<1|1] ^= 1;
    }
    lz[nd] = 0;
}

void flip(int nd, int l, int r, int L, int R) {
    push(nd, l, r);
    if (R < l || r < L) return;
    if (L <= l && r <= R) {
        swap(mx[nd], mn[nd]);
        if (l != r) { lz[nd<<1] ^= 1; lz[nd<<1|1] ^= 1; }
        return;
    }
    int mid = (l + r) >> 1;
    flip(nd<<1, l, mid, L, R);
    flip(nd<<1|1, mid+1, r, L, R);
    push(nd<<1, l, mid); push(nd<<1|1, mid+1, r);
    mx[nd] = mergeN(mx[nd<<1], mx[nd<<1|1]);
    mn[nd] = mergeN(mn[nd<<1], mn[nd<<1|1]);
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    if (!(cin >> n >> m)) return 0;
    a.assign(n+1, 0);
    for (int i = 1; i <= n; ++i) cin >> a[i];

    mx.assign(4*n+5, Node());
    mn.assign(4*n+5, Node());
    lz.assign(4*n+5, 0);

    build(1, 1, n);

    ll ans = 0, s = 0;
    for (int it = 0; it < m; ++it) {
        push(1, 1, n); // ensure root up-to-date
        if (mx[1].rl == -1) break; // no positive subarray left
        ll cur = mx[1].res;
        s += cur;
        ans = max(ans, s);
        flip(1, 1, n, mx[1].rl, mx[1].rr);
    }
    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...