Submission #1265653

#TimeUsernameProblemLanguageResultExecution timeMemory
1265653witek_cppDungeon 3 (JOI21_ho_t5)C++20
0 / 100
4091 ms2162688 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = (1LL<<60);

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int N, M;
    if (!(cin >> N >> M)) return 0;
    vector<int> A(N), B(N);
    for (int i = 0; i < N; ++i) cin >> A[i];
    for (int i = 0; i < N; ++i) cin >> B[i];

    // pref dla wygody (pref[0]=0, pref[i]=sum A[0..i-1])
    vector<ll> pref(N+1, 0);
    for (int i = 1; i <= N; ++i) pref[i] = pref[i-1] + A[i-1];

    for (int qi = 0; qi < M; ++qi) {
        int S, T; ll U;
        cin >> S >> T >> U;
        --S; --T; // zero-based floors: 0..N
        if (S == T) { cout << 0 << '\n'; continue; }

        // check impossible if some A[i] > U on route
        bool ok = true;
        ll totalNeeded = 0;
        for (int i = S; i < T; ++i) {
            if (A[i] > U) { ok = false; break; }
            totalNeeded += A[i];
        }
        if (!ok) { cout << -1 << '\n'; continue; }

        ll Ucap = min<ll>(U, totalNeeded);
        int L = T - S; // positions: p = 0..L (S..T), segments are 0..L-1
        int Mdim = L + 1; // we'll use indexing id = p*Mdim + x, x in [0..L]

        // precompute maxX[p] = largest x such that sum A[S+p .. S+x-1] <= Ucap
        vector<int> maxX(Mdim, -1);
        for (int p = 0; p <= L; ++p) {
            int lo = p, hi = L;
            int best = p;
            while (lo <= hi) {
                int mid = (lo + hi) >> 1;
                ll sum = pref[S + mid] - pref[S + p];
                if (sum <= Ucap) { best = mid; lo = mid + 1; }
                else hi = mid - 1;
            }
            maxX[p] = best; // there is always at least x = p (sum = 0)
        }

        // Number of potential nodes = Mdim * Mdim (we'll ignore invalid by checks)
        int totalStates = Mdim * Mdim;
        vector<ll> dist(totalStates, INF);
        auto idx = [&](int p, int x){ return p * Mdim + x; };

        // Dijkstra
        using pli = pair<ll,int>;
        priority_queue<pli, vector<pli>, greater<pli>> pq;

        // start (p=0,x=0)
        dist[idx(0,0)] = 0;
        pq.push({0, idx(0,0)});

        ll answer = INF;
        int targetId = idx(L, L);

        while (!pq.empty()) {
            auto [curCost, id] = pq.top(); pq.pop();
            if (curCost != dist[id]) continue;
            if (id == targetId) { answer = curCost; break; }
            int p = id / Mdim;
            int x = id % Mdim;
            // skip invalid node (x must be between p and maxX[p])
            if (x < p || x > maxX[p]) continue;

            // 1) move to next floor without buying if possible: (p,x) -> (p+1,x) cost 0
            if (p < L && x > p) { // x>p means energy >= A[S+p]
                int nid = idx(p+1, x);
                if (dist[nid] > curCost) {
                    dist[nid] = curCost;
                    pq.push({curCost, nid});
                }
            }

            // 2) buy "one segment" more: (p,x) -> (p,x+1) cost A[S+x] * B[S+p]
            if (x < Mdim - 1 && x+1 <= maxX[p]) {
                ll add = (ll)A[S + x] * (ll)B[S + p];
                int nid = idx(p, x+1);
                if (dist[nid] > curCost + add) {
                    dist[nid] = curCost + add;
                    pq.push({dist[nid], nid});
                }
            }
        }

        if (answer >= INF/4) cout << -1 << '\n';
        else cout << answer << '\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...