제출 #1276488

#제출 시각아이디문제언어결과실행 시간메모리
1276488mehrzadFestival (IOI25_festival)C++17
12 / 100
1038 ms2162688 KiB
#include <bits/stdc++.h> using namespace std; struct ScalingCoupon { int price; int mult; // T[i] ( > 1 ) int idx; // original index }; struct CheapCoupon { int price; int idx; }; static const long long INF = 4000000000000000000LL; // 4·10^18 // comparator: a before b <=> Pa*Ta/(Ta-1) < Pb*Tb/(Tb-1) bool scalingCmp(const ScalingCoupon& a, const ScalingCoupon& b) { __int128 left = (__int128)a.price * a.mult * (b.mult - 1); __int128 right = (__int128)b.price * b.mult * (a.mult - 1); if (left != right) return left < right; if (a.price != b.price) return a.price < b.price; return a.idx < b.idx; } vector<int> max_coupons(int A, vector<int> P, vector<int> T) { const int N = (int)P.size(); vector<ScalingCoupon> scaling; vector<CheapCoupon> cheap; for (int i = 0; i < N; ++i) { if (T[i] == 1) { cheap.push_back({P[i], i}); } else { scaling.push_back({P[i], T[i], i}); } } /* sort scaling coupons by the optimal order (Lemma 3) */ sort(scaling.begin(), scaling.end(), scalingCmp); /* sort cheap coupons by price, they will be taken greedily */ sort(cheap.begin(), cheap.end(), [](const CheapCoupon& a, const CheapCoupon& b) { if (a.price != b.price) return a.price < b.price; return a.idx < b.idx; }); int m = (int)scaling.size(); int c1 = (int)cheap.size(); /* DP: dp[i][k] – max tokens after first i scaling coupons, having taken exactly k of them */ vector<vector<long long>> dp(m + 1, vector<long long>(m + 1, -1)); vector<vector<char>> take(m + 1, vector<char>(m + 1, 0)); dp[0][0] = A; for (int i = 1; i <= m; ++i) { const ScalingCoupon& cur = scaling[i - 1]; for (int k = 0; k <= i; ++k) { // skip current coupon if (dp[i - 1][k] > dp[i][k]) { dp[i][k] = dp[i - 1][k]; take[i][k] = 0; } // take current coupon if (k > 0 && dp[i - 1][k - 1] >= cur.price) { __int128 tmp = (__int128)(dp[i - 1][k - 1] - cur.price) * cur.mult; long long nxt = (tmp > INF ? INF : (long long)tmp); if (nxt > dp[i][k]) { dp[i][k] = nxt; take[i][k] = 1; } } } } /* prefix sums of cheap coupons */ vector<long long> pref(c1 + 1, 0); for (int i = 0; i < c1; ++i) pref[i + 1] = pref[i] + cheap[i].price; /* choose the best k */ int bestTotal = -1; int bestK = 0; int bestCheapCnt = 0; long long bestTokens = 0; for (int k = 0; k <= m; ++k) { long long tok = dp[m][k]; if (tok < 0) continue; // maximal cheap coupons affordable int cheapCnt = (int)(upper_bound(pref.begin(), pref.end(), tok) - pref.begin()) - 1; int total = k + cheapCnt; if (total > bestTotal) { bestTotal = total; bestK = k; bestCheapCnt = cheapCnt; bestTokens = tok; } } /* reconstruct scaling part */ vector<int> answer; int i = m, k = bestK; while (i > 0) { if (take[i][k]) { answer.push_back(scaling[i - 1].idx); --k; } --i; } reverse(answer.begin(), answer.end()); /* add cheap coupons (cheapest first) */ for (int i = 0; i < bestCheapCnt; ++i) { answer.push_back(cheap[i].idx); } return answer; }
#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...