Submission #1209251

#TimeUsernameProblemLanguageResultExecution timeMemory
1209251jujuedvTricks of the Trade (CEOI23_trade)C++20
50 / 100
2910 ms17056 KiB
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

constexpr ll INF = ll(1e18);
constexpr int INF_IDX = int(1e9);

int n, k;
vector<int> a, b;

struct walker {
    int i, j;

    multiset<int> biggest_k, remainder;

    ll sum_b = 0;
    ll sum_biggest_k = 0;

    walker(int x) { // interval from x to x
        i = j = x;
        add_elem(x);
    }

    ll value() {
        if(j - i + 1 >= k)
            return sum_biggest_k - sum_b;
        else
            return -INF;
    }

    void add_elem(int x) {
        sum_b += b[x];
        sum_biggest_k += a[x];
        biggest_k.insert(a[x]);

        if(biggest_k.size() > k) {
            auto it = biggest_k.begin();
            sum_biggest_k -= *it;
            remainder.insert(*it);
            biggest_k.erase(it);
        }
    }

    void remove_elem(int x) {
        sum_b -= b[x];
        auto it = biggest_k.find(a[x]);
        if(it != biggest_k.end()) {
            sum_biggest_k -= a[x];
            biggest_k.erase(it);
        } else {
            remainder.erase(remainder.find(a[x]));
        }

        if(biggest_k.size() < k && remainder.size() > 0) {
            auto it2 = --remainder.end();
            sum_biggest_k += *it2;
            biggest_k.insert(*it2);
            remainder.erase(it2);
        }
    }

    void decrease_i() {
        add_elem(--i);
    }

    void increase_i() {
        remove_elem(i++);
    }

    void decrease_j() {
        remove_elem(j--);
    }

    void increase_j() {
        add_elem(++j);
    }

    void move(int ii, int jj) {
        while(i > ii) decrease_i();
        while(j < jj) increase_j();

        while(i < ii) increase_i();
        while(j > jj) decrease_j();
    }
};

vector<ll> best_val_starting_at;
vector<int> opt_min;

void comp_opt_min(int l, int r, int opt_lo, int opt_hi, walker& walk) {
    if(l > r) return;

    int m = (l + r)/2;
    ll best_val = -INF;
    ll opt = INF_IDX;
    for(int j = max(opt_lo, m); j <= opt_hi; ++j) {
        walk.move(m, j);
        if(walk.value() > best_val) {
            best_val = walk.value();
            opt = j;
        }
    }

    opt_min[m] = opt;
    best_val_starting_at[m] = best_val;

    if(opt == INF_IDX) opt = opt_hi; // prevent weird edge cases

    comp_opt_min(l, m-1, opt_lo, opt, walk);
    comp_opt_min(m+1, r, opt, opt_hi, walk);
}

int main() {
    cin >> n >> k;

    a.resize(n);
    b.resize(n);

    for(auto &x : b) cin >> x;
    for(auto &x : a) cin >> x;

    opt_min.resize(n);
    best_val_starting_at.resize(n);

    {
        walker walk(n/2);
        comp_opt_min(0, n-1, 0, n-1, walk);
    }

    ll max_val = -INF;
    for(int i = 0; i < n; ++i) {
        max_val = max(max_val, best_val_starting_at[i]);
    }

    cout << max_val << endl;

}

#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...