Submission #1243444

#TimeUsernameProblemLanguageResultExecution timeMemory
1243444aykhn나일강 (IOI24_nile)C++20
32 / 100
78 ms15432 KiB
#include "nile.h"
#include <vector>
#include <algorithm>

using ll = long long;
static const ll NEG_INF = -(1LL<<60);

// 2x2 max-plus matrix
struct Mat {
    ll a[2][2];
};

// Max-plus multiplication: C = B * A
static Mat mmul(const Mat &B, const Mat &A) {
    Mat C;
    for(int i = 0; i < 2; i++) {
        for(int j = 0; j < 2; j++) {
            ll v = NEG_INF;
            for(int k = 0; k < 2; k++) {
                ll x = B.a[i][k] + A.a[k][j];
                if(x > v) v = x;
            }
            C.a[i][j] = v;
        }
    }
    return C;
}

std::vector<long long> calculate_costs(
    std::vector<int> W, std::vector<int> A,
    std::vector<int> B, std::vector<int> E) {
    int N = (int)W.size();
    int Q = (int)E.size();
    
    // base sum if all alone
    ll sumA = 0;
    for(int i = 0; i < N; i++) sumA += A[i];
    
    // handle trivial N=1
    if(N == 1) {
        std::vector<ll> R(Q, sumA);
        return R;
    }
    
    // build items sorted by weight
    struct Item { int w; ll d; };
    std::vector<Item> it(N);
    for(int i = 0; i < N; i++) {
        it[i].w = W[i];
        it[i].d = (ll)A[i] - (ll)B[i];
    }
    std::sort(it.begin(), it.end(), [](auto &L, auto &R){ return L.w < R.w; });
    
    // compute gaps (gap, index)
    // index k means between it[k-1] and it[k]
    std::vector<std::pair<int,int>> gaps;
    gaps.reserve(N-1);
    for(int k = 1; k < N; k++) {
        gaps.emplace_back(it[k].w - it[k-1].w, k);
    }
    std::sort(gaps.begin(), gaps.end());
    
    // sort queries (D, original idx)
    std::vector<std::pair<int,int>> qs(Q);
    for(int j = 0; j < Q; j++) qs[j] = {E[j], j};
    std::sort(qs.begin(), qs.end());
    
    // build seg-tree size = next pow2 >= N
    int SZ = 1;
    while(SZ < N) SZ <<= 1;
    std::vector<Mat> seg(2*SZ);
    
    // identity matrix in max-plus
    Mat I;
    I.a[0][0] = 0;      I.a[0][1] = NEG_INF;
    I.a[1][0] = NEG_INF;I.a[1][1] = 0;
    // off-edge matrix
    Mat Off;
    Off.a[0][0] = NEG_INF; Off.a[0][1] = 0;
    Off.a[1][0] = NEG_INF; Off.a[1][1] = 0;
    
    // init leaves
    for(int i = 0; i < SZ; i++) {
        if(i >= 1 && i < N) seg[SZ + i] = Off;
        else seg[SZ + i] = I;
    }
    // build internals
    for(int i = SZ-1; i >= 1; i--) {
        seg[i] = mmul(seg[2*i+1], seg[2*i]);
    }
    
    std::vector<ll> R(Q);
    int ptr = 0;
    // process queries
    for(auto &qq : qs) {
        int D = qq.first;
        int qi = qq.second;
        // activate gaps with gap <= D
        while(ptr < (int)gaps.size() && gaps[ptr].first <= D) {
            int k = gaps[ptr].second;
            // on-edge matrix at k
            Mat On = Off;
            ll sumd = it[k].d + it[k-1].d;
            On.a[1][0] = sumd;
            // update leaf k
            int pos = SZ + k;
            seg[pos] = On;
            pos >>= 1;
            while(pos) {
                seg[pos] = mmul(seg[2*pos+1], seg[2*pos]);
                pos >>= 1;
            }
            ptr++;
        }
        // seg[1] holds full product; matched = max(dp[N-1], dp[N]) = max(a[1][0], a[1][1])
        Mat &M = seg[1];
        ll matched = M.a[1][0] > M.a[1][1] ? M.a[1][0] : M.a[1][1];
        R[qi] = sumA - matched;
    }
    return R;
}
#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...