Submission #1256075

#TimeUsernameProblemLanguageResultExecution timeMemory
1256075TurkhuuSouvenirs (IOI25_souvenirs)C++20
100 / 100
12 ms420 KiB
#include "souvenirs.h"
#include <bits/stdc++.h>
#define FOR(i, a, b) for (auto i = (a); i <= (b); i++)
#define ROF(i, a, b) for (auto i = (a); i >= (b); i--)
using namespace std;
using ll = long long;
int N;
vector<bool> known;
vector<ll> P;
vector<int> C;
vector<pair<set<int>, ll>> res;
map<ll, pair<vector<int>, ll>> mp;
void know(int i, ll x) {
    if (known[i]) return;
    // assert(!known[i]);
    P[i] = x, known[i] = 1;
    for (auto& p : res) {
        auto& s = p.first;
        auto& x = p.second;
        if (s.count(i)) {
            s.erase(i);
            x -= P[i];
        }
        if (s.size() == 1) know(*s.begin(), x);
    }
}
void cleanup() {
    for (auto [s, x] : res) if (s.size() == 1) know(*s.begin(), x);
    while (1) {
        auto it = res.begin();
        while (it != res.end() && !(*it).first.empty()) it++;
        if (it == res.end()) break;
        res.erase(it);
    }
}
pair<set<int>, ll> query(ll M) {
    vector<int> v; ll x;
    bool f = 0;
    if (mp.find(M) == mp.end()) mp[M] = transaction(M), f = 1;
    tie(v, x) = mp[M];
    x = M - x;
    // if (f) {
    //     cout << M << " :: " << x << " :: ";
    //     for (int i : v) cout << i << " ";
    //     cout << "\n";
    // }
    set<int> s;
    for (int i : v) {
        if (f) C[i]++;
        if (!known[i]) s.insert(i);
        else x -= P[i];
    }
    res.push_back({s, x});
    cleanup();
    return {s, x};
}
void buy_rest() {
    FOR(i, 0, N - 1) {
        // if (!(C[i] <= i)) while (1) {}
        while (C[i]++ < i) transaction(P[i]);
    }
}
void solve() {
    while (1) {
        if (known == vector<bool>(N, 1)) return;
        bool f = 0;
        int k = -1;
        ROF(i, N - 1, 0) {
            if (!known[i]) f = 1;
            else if (f) {k = i; break;}
        }
        if (mp.find(P[k] - 1) == mp.end()) {
            query(P[k] - 1);
            continue;
        }
        ll mn = 1e18;
        for (auto [s, x] : res) mn = min(mn, x / (int)s.size());
        query(mn);
    }
}
// void solve(int S) {
//     // assert(known[S]);
//     bool all = 1;
//     FOR(i, S, N - 1) if (!known[i]) all = 0;
//     if (all) return;
//     if (known[S + 1]) {
//         solve(S + 1);
//         return;
//     }

//     auto [s, x] = query(P[S] - 1);
//     while (1) {
//         for (auto [s, x] : res) if (s.size() == 1) know(*s.begin(), x);
//         ROF(i, N - 1, S) if (known[i]) solve(i);
//         while (1) {
//             auto it = res.begin();
//             while (it != res.end() && !(*it).first.empty()) it++;
//             if (it == res.end()) break;
//             res.erase(it);
//         }
//         bool duus = 1;
//         for (auto [s, x] : res) if (!s.empty() && *s.rbegin() >= S && *s.begin() >= S) duus = 0;
//         if (duus) break;
//         ll mn = 1e18;
//         for (auto [S, X] : res) {
//             mn = min(mn, X / (int)S.size());
//         }
//         tie(s, x) = query(mn);
//     }
//     ROF(i, N - 1, S) if (known[i]) solve(i);
// }
void buy_souvenirs(int _N, long long P0) {
    N = _N, P.resize(N), C.resize(N), known.resize(N);
    know(0, P0);
    solve();
    buy_rest();
}
#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...