Submission #1342247

#TimeUsernameProblemLanguageResultExecution timeMemory
1342247tutithuybi123선물 (IOI25_souvenirs)C++20
100 / 100
12 ms412 KiB
#include "souvenirs.h"
#include <bits/stdc++.h>
using namespace std;

using int64 = long long;

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

    // depend[i]: one equation for unknown prices in this set
    // sumv[i] = sum of prices in depend[i]
    vector<set<int>> depend(N);
    vector<long long> sumv(N, 0);

    // count how many souvenirs of each type have already been bought
    // during the discovery phase
    vector<int> bought(N, 0);

    auto apply_query = [&](long long M, set<int>& unknown_set, long long& unknown_sum) {
        auto res = transaction(M);
        const vector<int>& L = res.first;
        long long R = res.second;

        set<int> s;
        for (int x : L) {
            s.insert(x);
            bought[x]++;
        }

        long long spent = M - R;

        // remove already known prices from the equation
        for (int i = 0; i < N; ++i) {
            if (price[i] != -1 && s.count(i)) {
                spent -= price[i];
                s.erase(i);
            }
        }

        unknown_set = s;
        unknown_sum = spent;
    };

    while (true) {
        int left = 0;
        for (int i = 0; i < N; ++i) {
            if (price[i] == -1) left++;
        }
        if (left == 0) break;

        bool progressed = false;
        bool have_unknown_suffix = false;

        for (int i = N - 1; i >= 0; --i) {
            if (price[i] == -1) have_unknown_suffix = true;

            // From a known price price[i], query price[i]-1 to get
            // an equation involving only cheaper unknown items.
            if (price[i] != -1 && have_unknown_suffix) {
                set<int> s;
                long long sm = 0;
                apply_query(price[i] - 1, s, sm);

                depend[i + 1] = s;
                sumv[i + 1] = sm;
                progressed = true;
                break;
            }

            // If an equation contains exactly one unknown, we recover it.
            if (!depend[i].empty() && depend[i].size() == 1) {
                int x = *depend[i].begin();
                price[x] = sumv[i];

                // substitute into all stored equations
                for (int j = 0; j < N; ++j) {
                    if (depend[j].count(x)) {
                        depend[j].erase(x);
                        sumv[j] -= price[x];
                    }
                }

                depend[i].clear();
                sumv[i] = 0;
                progressed = true;
                break;
            }

            // Otherwise, split the equation by querying the average.
            if (!depend[i].empty()) {
                long long x = sumv[i] / (long long)depend[i].size();

                set<int> s;
                long long sm = 0;
                apply_query(x, s, sm);

                int k = *s.begin();
                depend[k] = s;
                sumv[k] = sm;

                progressed = true;
                break;
            }
        }

        if (!progressed) break;
    }

    // Top up counts to exactly i souvenirs of type i.
    for (int i = 1; i < N; ++i) {
        while (bought[i] < i) {
            transaction(price[i]);
            bought[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...