Submission #1254699

#TimeUsernameProblemLanguageResultExecution timeMemory
1254699fasterthanyouFestival (IOI25_festival)C++20
32 / 100
86 ms9032 KiB
#include <iostream> #include <vector> #include <numeric> #include <algorithm> #include <climits> // For LLONG_MAX // Use a struct to keep coupon properties and original index together. struct Coupon { int id; long long p; // Use long long for price to handle large numbers. int t; }; /** * @brief Solves the coupon buying problem to maximize the number of coupons purchased. * * @param A_int The initial number of tokens. * @param P A vector of coupon prices. * @param T A vector of coupon multipliers. * @return A vector of 0-indexed coupon IDs in the optimal buying order. */ std::vector<int> max_coupons(int A_int, std::vector<int> P, std::vector<int> T) { long long A = A_int; int N = P.size(); // 1. Create a vector of Coupon structs to store all properties. std::vector<Coupon> coupons(N); for (int i = 0; i < N; ++i) { coupons[i] = {i, (long long)P[i], T[i]}; } // 2. Sort coupons using the custom greedy comparator. std::sort(coupons.begin(), coupons.end(), [](const Coupon& c1, const Coupon& c2) { // T=1 coupons are always worse; they are processed after T>1 coupons. if (c1.t == 1 && c2.t > 1) return false; // c2 comes first if (c1.t > 1 && c2.t == 1) return true; // c1 comes first // If both are T=1, cheaper ones are better. if (c1.t == 1 && c2.t == 1) { return c1.p < c2.p; } // If both have T > 1, compare their "value" P*T/(T-1). // Using long double is a standard-compliant way to get high precision. long double v1 = static_cast<long double>(c1.p) * c1.t / (c1.t - 1); long double v2 = static_cast<long double>(c2.p) * c2.t / (c2.t - 1); // Tie-break with price to ensure a consistent, stable order. if (v1 != v2) { return v1 < v2; } return c1.p < c2.p; }); // 3. Binary search for the maximum number of coupons (k). auto check = [&](int k) { if (k == 0) return true; long long current_tokens = A; for (int i = 0; i < k; ++i) { long long price = coupons[i].p; int mult = coupons[i].t; if (current_tokens < price) { return false; } current_tokens -= price; if (mult > 1) { // Check for impending overflow before multiplication. if (current_tokens > LLONG_MAX / mult) { // If it would overflow, tokens become effectively infinite. // LLONG_MAX is a safe sentinel value for this purpose. current_tokens = LLONG_MAX; } else { current_tokens *= mult; } } } return true; }; int low = 0, high = N; int best_k = 0; while (low <= high) { int mid = low + (high - low) / 2; if (check(mid)) { best_k = mid; low = mid + 1; } else { high = mid - 1; } } // 4. Construct the result vector with the IDs of the first `best_k` coupons. std::vector<int> result; result.reserve(best_k); for (int i = 0; i < best_k; ++i) { result.push_back(coupons[i].id); } return result; }
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...