Submission #1269639

#TimeUsernameProblemLanguageResultExecution timeMemory
1269639brendonwSouvenirs (IOI25_souvenirs)C++20
100 / 100
12 ms420 KiB
#include "souvenirs.h"
#include <bits/stdc++.h>

using namespace std;
using ll = long long;

void buy_souvenirs(int n, ll p0) {
	vector<ll> prices(n, -1);
	prices[0] = p0;
	vector<ll> cnt(n);

	// transaction on nxt
	vector<pair<vector<ll>, ll>> cur;
	map<ll, pair<vector<ll>, ll>> cache;
	auto get = [&](ll cost) {
		if (cache.count(cost) == 1) {
			return cache[cost];
		}
		auto [vals, over] = transaction(cost);
		for (auto &val: vals) {
			cnt[val]++;
		}
		return cache[cost] = pair{vector<ll>(vals.begin(), vals.end()), over};
	};
	vector<bool> used(n);
	while (count(prices.begin(), prices.end(), -1) != 0) {
		auto update = [&](vector<ll> vals, ll sum) -> pair<vector<ll>, ll> {
			vector<ll> new_vals;
			for (auto &val: vals) {
				if (prices[val] == -1) {
					new_vals.push_back(val);
				} else {
					sum -= prices[val];
				}
			}
			return {new_vals, sum};
		};
		auto update_cur = [&]() {
			vector<pair<vector<ll>, ll>> new_cur;
			for (auto [vals, sum]: cur) {
				tie(vals, sum) = update(vals, sum);
				if (!vals.empty()) {
					new_cur.push_back({vals, sum});
				}
			}
			cur = new_cur;
		};
		auto clear = [&]() {
			while (true) {
				update_cur();
				bool changed = false;
				for (auto &[vals, sum]: cur) {
					if (vals.size() == 1) {
						prices[vals[0]] = sum;
						changed = true;
					}
				}
				if (!changed) {
					break;
				}
			}
		};
		bool started = false;

		while (!cur.empty() || !started) {
			started = true;
			ll cost = 0;
			auto next = [&](ll i) -> ll {
				for (; i < n; ++i) {
					if (prices[i] == -1) {
						return prices[i - 1] - 1;
					}
				}
				return -1;
			};
			if (cur.empty()) {
				cost = next(0);
			} else {
				std::sort(cur.begin(), cur.end(), [](auto a, auto b) {
					return make_pair(a.first.back(), a.first.front()) > make_pair(b.first.back(), b.first.front());
				});
//				for (int i = 0; i < cur.size(); ++i) {
//
//					cout << "{ ";
//					for (auto &val: cur[i].first) {
//						cout << val << " ";
//					}
//					cout << "}" << " " << cur[i].second << '\n';
//
//				}
//				cout << "-------------------------" << '\n';
				cost = cur.front().second / cur.front().first.size();
			}
//			cost = next();
			while (count(prices.begin(), prices.end(), -1) != 0) {
//				cout << cost << endl;
//				cout << cnt[4] << endl;
				auto [vals, over] = get(cost);
//				for (auto &val: vals) {
//					cnt[val]++;
//				}
				ll old = vals[0];
				ll sum = cost - over;
				tie(vals, sum) = update(vals, sum);
				cur.push_back({vals, sum});
				if (vals.size() == 0) {
					cost = next(old);
					if (cost == -1) {
						break;
					}
				} else if (vals.size() == 1) {
					prices[vals[0]] = sum;
					clear();
					cost = next(vals[0]);
					if (cost == -1) {
						break;
					}
				} else {
					cost = sum / vals.size();
				}
			}
			clear();
		}

	}
	for (int i = 0; i < n; ++i) {
		while (cnt[i] < i) {
			assert(transaction(prices[i]).first.size() == 1);
			cnt[i]++;
		}
//		assert(cnt[i] == i);
	}

	return;
}
#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...