Submission #1295815

#TimeUsernameProblemLanguageResultExecution timeMemory
1295815lucas110550Festival (IOI25_festival)C++20
5 / 100
76 ms9780 KiB
#include <bits/stdc++.h> using namespace std; vector<int> max_coupons(int A, vector<int> P, vector<int> T) { int n = (int)P.size(); // L1: (price, index) for T[i] == 1 vector<pair<long long,int>> L1; // L2: coupons with t > 1 struct Coupon { long long p; long long t; int idx; }; vector<Coupon> L2; for (int i = 0; i < n; ++i) { if (T[i] == 1) { L1.push_back({(long long)P[i], i}); } else { L2.push_back({(long long)P[i], (long long)T[i], i}); } } // Sort L1 by price sort(L1.begin(), L1.end(), [](const pair<long long,int> &a, const pair<long long,int> &b) { return a.first < b.first; }); // Sort L2 with custom comparator if (!L2.empty()) { sort(L2.begin(), L2.end(), [](const Coupon &a, const Coupon &b) { // Use __int128 to avoid overflow __int128 p1 = a.p, t1 = a.t; __int128 p2 = b.p, t2 = b.t; __int128 left = p1 * t1 * (t2 - 1); __int128 right = p2 * t2 * (t1 - 1); return left < right; }); } // Prefix sums for L1 prices vector<long long> prefix1; prefix1.reserve(L1.size() + 1); prefix1.push_back(0); for (auto &pr : L1) { long long price = pr.first; long long next_val = prefix1.back() + price; prefix1.push_back(next_val); } const int max_set2 = 100; const long long CLAMP_MAX = (long long)1e18; // dp[k] = max money achievable after using k coupons from L2 vector<long long> dp(max_set2 + 1, -1); // -1 means unreachable dp[0] = (long long)A; // parent[k] = (previous k, original index of coupon) vector<pair<int,int>> parent(max_set2 + 1, {-1, -1}); // Knapsack over L2 coupons for (const auto &coupon : L2) { long long p = coupon.p; long long t = coupon.t; int orig_i = coupon.idx; for (int k = max_set2 - 1; k >= 0; --k) { if (dp[k] < p || dp[k] < 0) continue; long long current_val = dp[k]; __int128 new_val_128 = (__int128)(current_val - p) * t; long long new_val; if (new_val_128 > CLAMP_MAX) new_val = CLAMP_MAX; else new_val = (long long)new_val_128; if (new_val > dp[k + 1]) { dp[k + 1] = new_val; parent[k + 1] = {k, orig_i}; } } } // Choose best combination of L2 coupons (k2) and L1 items (m) int best_total = 0; int best_k2 = 0; int best_m = 0; for (int k2 = 0; k2 <= max_set2; ++k2) { if (dp[k2] < 0) continue; long long money = dp[k2]; // m = number of items from L1 we can buy with 'money' int m = (int)(upper_bound(prefix1.begin(), prefix1.end(), money) - prefix1.begin()) - 1; int total = k2 + m; if (total > best_total) { best_total = total; best_k2 = k2; best_m = m; } } // Reconstruct which L2 coupons were used vector<int> seq_set2; { int k = best_k2; while (k > 0) { auto [prev_k, idx] = parent[k]; seq_set2.push_back(idx); k = prev_k; } reverse(seq_set2.begin(), seq_set2.end()); } // Take first best_m items from L1 (they are cheapest due to sorting) vector<int> seq_set1; for (int i = 0; i < best_m; ++i) { seq_set1.push_back(L1[i].second); } // Return concatenation of seq_set2 + seq_set1 vector<int> result; result.reserve(seq_set2.size() + seq_set1.size()); result.insert(result.end(), seq_set2.begin(), seq_set2.end()); result.insert(result.end(), seq_set1.begin(), seq_set1.end()); 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...