Submission #1321171

#TimeUsernameProblemLanguageResultExecution timeMemory
1321171SmuggingSpunFestival (IOI25_festival)C++20
100 / 100
141 ms200228 KiB
#include "festival.h" #include<bits/stdc++.h> using namespace std; typedef long long ll; const ll INF = 1e18; template<class T>bool minimize(T& a, T b){ if(a > b){ a = b; return true; } return false; } template<class T>bool maximize(T& a, T b){ if(a < b){ a = b; return true; } return false; } int n; ll A; vector<int>p, t; namespace sub1{ vector<int>solve(){ vector<int>R(n), ans; iota(R.begin(), R.end(), 0); sort(R.begin(), R.end(), [&] (int i, int j){ return p[i] < p[j]; }); for(int& i : R){ if((A -= p[i]) < 0){ break; } ans.push_back(i); } return ans; } } namespace sub23{ vector<int>solve(){ vector<vector<int>>part(2); for(int i = 0; i < n; i++){ part[t[i] - 1].push_back(i); } for(int i = 0; i < 2; i++){ sort(part[i].begin(), part[i].end(), [&] (int x, int y){ return p[x] < p[y]; }); } vector<ll>f(1, 0); for(int& i : part[0]){ f.push_back(f.back() + p[i]); } f[0] = -1; function<int(ll)>calc = [&] (ll x){ return upper_bound(f.begin(), f.end(), x) - f.begin() - 1; }; int best = calc(A), cnt_2 = 0; for(int i = 0; i < part[1].size(); i++){ if(A < p[part[1][i]]){ break; } if(maximize(best, i + 1 + calc(A = min((A - p[part[1][i]]) << 1LL, INF)))){ cnt_2 = i + 1; } } vector<int>ans(part[1].begin(), part[1].begin() + cnt_2); for(int i = 0; i < best - cnt_2; i++){ ans.push_back(part[0][i]); } return ans; } } namespace sub4{ ll dp[71][71][71][71]; short trace[71][71][71][71]; vector<int>solve(){ vector<vector<int>>part(5); for(int i = 0; i < n; i++){ part[t[i]].push_back(i); } for(int i = 1; i < 5; i++){ sort(part[i].begin(), part[i].end(), [&] (int x, int y){ return p[x] < p[y]; }); } memset(dp, -0x0f, sizeof(dp)); dp[0][0][0][0] = A; vector<int>N; int best = 0; for(int n1 = 0; n1 <= part[1].size(); n1++){ for(int n2 = 0; n2 <= part[2].size(); n2++){ for(int n3 = 0; n3 <= part[3].size(); n3++){ for(int n4 = 0; n4 <= part[4].size(); n4++){ ll x = dp[n1][n2][n3][n4]; if(x < 0){ continue; } minimize(x, INF); if(maximize(best, n1 + n2 + n3 + n4)){ N = {-1, n1, n2, n3, n4}; } if(n1 < part[1].size() && x >= p[part[1][n1]] && maximize(dp[n1 + 1][n2][n3][n4], x - p[part[1][n1]])){ trace[n1 + 1][n2][n3][n4] = 1; } if(n2 < part[2].size() && x >= p[part[2][n2]] && maximize(dp[n1][n2 + 1][n3][n4], (x - p[part[2][n2]]) << 1LL)){ trace[n1][n2 + 1][n3][n4] = 2; } if(n3 < part[3].size() && x >= p[part[3][n3]] && maximize(dp[n1][n2][n3 + 1][n4], (x - p[part[3][n3]]) * 3)){ trace[n1][n2][n3 + 1][n4] = 3; } if(n4 < part[4].size() && x >= p[part[4][n4]] && maximize(dp[n1][n2][n3][n4 + 1], (x - p[part[4][n4]]) << 2LL)){ trace[n1][n2][n3][n4 + 1] = 4; } } } } } vector<int>ans; for(int i = 0; i < best; i++){ int x = trace[N[1]][N[2]][N[3]][N[4]]; ans.push_back(part[x][N[x] - 1]); N[x]--; } reverse(ans.begin(), ans.end()); return ans; } } namespace sub5{ bool check_subtask(){ vector<int>idx(n); iota(idx.begin(), idx.end(), 0); sort(idx.begin(), idx.end(), [&] (int x, int y){ return ll(p[x]) * t[x] * t[y] + ll(p[y]) * t[y] < ll(p[y]) * t[x] * t[y] + ll(p[x]) * t[x]; }); ll x = A; for(int& i : idx){ if(x < p[i]){ return false; } x = min((x - p[i]) * t[i], INF); } return true; } vector<int>solve(){ vector<int>idx(n); iota(idx.begin(), idx.end(), 0); sort(idx.begin(), idx.end(), [&] (int x, int y){ return ll(p[x]) * t[x] * t[y] + ll(p[y]) * t[y] < ll(p[y]) * t[x] * t[y] + ll(p[x]) * t[x]; }); return idx; } } namespace sub6{ bool check_subtask(){ for(int i = 0; i < n; i++){ if((A - p[i]) * t[i] >= A){ return false; } } return true; } vector<int>solve(){ vector<int>idx, other; for(int i = 0; i < n; i++){ if(t[i] > 1){ idx.push_back(i); } else{ other.push_back(i); } } sort(other.begin(), other.end(), [&] (int x, int y){ return p[x] < p[y]; }); vector<ll>f(1, 0); for(int& i : other){ f.push_back(f.back() + p[i]); } f[0] = -1; function<int(ll)>calc = [&] (ll x){ return upper_bound(f.begin(), f.end(), x) - f.begin() - 1; }; sort(idx.begin(), idx.end(), [&] (int x, int y){ return ll(p[x]) * t[x] * t[y] + ll(p[y]) * t[y] < ll(p[y]) * t[x] * t[y] + ll(p[x]) * t[x]; }); vector<vector<ll>>dp(idx.size() + 1, vector<ll>(36, -INF)); vector<vector<bool>>trace(idx.size() + 1, vector<bool>(20, false)); dp[0][0] = A; for(int i = 0; i < idx.size(); i++){ for(int j = 0; j < 36; j++){ ll x = dp[i][j]; if(maximize(dp[i + 1][j], x)){ trace[i + 1][j] = false; } if(j < 35 && x >= p[idx[i]] && maximize(dp[i + 1][j + 1], (x - p[idx[i]]) * t[idx[i]])){ trace[i + 1][j + 1] = true; } } } int best_n1 = 0, best = -1; for(int i = 0; i < 36; i++){ if(dp[idx.size()][i] > -1 && maximize(best, i + calc(dp[idx.size()][i]))){ best_n1 = i; } } vector<int>ans; for(int i = idx.size(), j = best_n1; i > 0; i--){ if(trace[i][j]){ j--; ans.push_back(idx[i - 1]); } } reverse(ans.begin(), ans.end()); for(int i = 0; i < best - best_n1; i++){ ans.push_back(other[i]); } return ans; } } namespace sub7{ vector<int>solve(){ vector<int>idx, other; for(int i = 0; i < n; i++){ if(t[i] > 1){ idx.push_back(i); } else{ other.push_back(i); } } sort(other.begin(), other.end(), [&] (int x, int y){ return p[x] < p[y]; }); vector<ll>f(1, 0); for(int& i : other){ f.push_back(f.back() + p[i]); } f[0] = -1; function<int(ll)>calc = [&] (ll x){ return upper_bound(f.begin(), f.end(), x) - f.begin() - 1; }; sort(idx.begin(), idx.end(), [&] (int x, int y){ return ll(p[x]) * t[x] * t[y] + ll(p[y]) * t[y] < ll(p[y]) * t[x] * t[y] + ll(p[x]) * t[x]; }); vector<int>init_ans; int pref = 0; while(pref < idx.size()){ ll nA = (A - p[idx[pref]]) * t[idx[pref]]; if(nA < A){ break; } A = min(nA, INF); init_ans.push_back(idx[pref++]); } int idx_sz = int(idx.size()) - pref; vector<vector<ll>>dp(idx_sz + 1, vector<ll>(36, -INF)); vector<vector<bool>>trace(idx_sz + 1, vector<bool>(20, false)); dp[0][0] = A; for(int i = 0; i < idx_sz; i++){ for(int j = 0; j < 36; j++){ ll x = dp[i][j]; if(maximize(dp[i + 1][j], x)){ trace[i + 1][j] = false; } if(j < 35 && x >= p[idx[i + pref]] && maximize(dp[i + 1][j + 1], (x - p[idx[i + pref]]) * t[idx[i + pref]])){ trace[i + 1][j + 1] = true; } } } int best_n1 = 0, best = -1; for(int i = 0; i < 36; i++){ if(dp[idx_sz][i] > -1 && maximize(best, i + calc(dp[idx_sz][i]))){ best_n1 = i; } } vector<int>ans; for(int i = idx_sz, j = best_n1; i > 0; i--){ if(trace[i][j]){ j--; ans.push_back(idx[i + pref - 1]); } } reverse(ans.begin(), ans.end()); ans.insert(ans.begin(), init_ans.begin(), init_ans.end()); for(int i = 0; i < best - best_n1; i++){ ans.push_back(other[i]); } return ans; } } vector<int>max_coupons(int _A, vector<int>_P, vector<int>_T){ A = _A; swap(p, _P); swap(t, _T); n = p.size(); if(*max_element(t.begin(), t.end()) == 1){ return sub1::solve(); } if(*max_element(t.begin(), t.end()) <= 2){ return sub23::solve(); } if(n <= 70){ return sub4::solve(); } if(sub5::check_subtask()){ return sub5::solve(); } return sub6::check_subtask() ? sub6::solve() : sub7::solve(); }
#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...