Submission #1274814

#TimeUsernameProblemLanguageResultExecution timeMemory
1274814mehrzadSouvenirs (IOI25_souvenirs)C++20
100 / 100
13 ms400 KiB
#include "souvenirs.h"
#include <bits/stdc++.h>
using namespace std;

struct Equation {
    vector<int> L;   // indices of bought types
    long long sum;   // M - R  = Σ_{i∈L} P[i]
};

void buy_souvenirs(int N, long long P0) {
    // ------------------------------------------------------------
    // data
    vector<long long> price(N, -1);       // unknown -> -1, price[0] known
    price[0] = P0;

    vector<int> need(N, 0);               // need[i] = i
    for (int i = 0; i < N; ++i) need[i] = i;
    vector<int> have(N, 0);               // already bought copies

    vector<Equation> eqs;                 // all equations obtained

    long long UB = P0 - 1;                // safe upper bound for the cheapest unknown

    // ------------------------------------------------------------
    // Phase A – discover all prices
    while (true) {
        bool allKnown = true;
        for (int i = 1; i < N; ++i)
            if (price[i] == -1) { allKnown = false; break; }
        if (allKnown) break;                      // finished

        // ----- perform a safe transaction -----
        auto res = transaction(UB);
        const vector<int> &L = res.first;
        long long R = res.second;

        // update bought counters
        for (int idx : L) {
            // type 0 must never appear, but we ignore it if it does
            if (idx == 0) continue;
            ++have[idx];
        }

        long long sum = UB - R;                    // Σ P[i] of the bought types
        eqs.push_back({L, sum});

        // ----- try to deduce new prices -----
        bool changed = true;
        while (changed) {
            changed = false;
            for (auto &e : eqs) {
                long long knownSum = 0;
                int unknownCnt = 0;
                int unknownIdx = -1;
                for (int idx : e.L) {
                    if (price[idx] != -1) knownSum += price[idx];
                    else {
                        ++unknownCnt;
                        unknownIdx = idx;
                    }
                }
                if (unknownCnt == 1) {
                    long long val = e.sum - knownSum;
                    if (price[unknownIdx] == -1) {
                        price[unknownIdx] = val;
                        changed = true;
                    }
                }
            }
        }

        // ----- compute a new safe upper bound -----
        long long newUB = P0 - 1;                  // start with a trivial bound

        // from equations (average of still unknown part)
        for (const auto &e : eqs) {
            long long knownSum = 0;
            int unknownCnt = 0;
            for (int idx : e.L) {
                if (price[idx] != -1) knownSum += price[idx];
                else ++unknownCnt;
            }
            if (unknownCnt > 0) {
                long long cand = (e.sum - knownSum) / unknownCnt;
                if (cand < newUB) newUB = cand;
            }
        }

        // from already known, more expensive prices
        int maxUnknown = -1;                       // largest index still unknown
        for (int i = N - 1; i >= 1; --i)
            if (price[i] == -1) { maxUnknown = i; break; }

        if (maxUnknown != -1) {
            for (int i = 1; i < maxUnknown; ++i)   // more expensive known prices
                if (price[i] != -1) {
                    long long cand = price[i] - 1;
                    if (cand < newUB) newUB = cand;
                }
        }

        if (newUB < 1) newUB = 1;                 // never zero
        UB = newUB;
    }

    // ------------------------------------------------------------
    // Phase B – buy the remaining copies (now all prices are known)
    for (int i = 1; i < N; ++i) {
        while (have[i] < need[i]) {
            // one copy of type i
            transaction(price[i]);    // the returned list must be {i}, R = 0
            ++have[i];
        }
    }
}
#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...