Submission #152449

#TimeUsernameProblemLanguageResultExecution timeMemory
152449qkxwsmThe Big Prize (IOI17_prize)C++14
20 / 100
274 ms11496 KiB
#include "prize.h" #include <bits/stdc++.h> #include <ext/pb_ds/assoc_container.hpp> using namespace std; using namespace __gnu_pbds; template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>; template<class T, class U> void ckmin(T &a, U b) { if (a > b) a = b; } template<class T, class U> void ckmax(T &a, U b) { if (a < b) a = b; } #define MP make_pair #define PB push_back #define LB lower_bound #define UB upper_bound #define fi first #define se second #define FOR(i, a, b) for (auto i = (a); i < (b); i++) #define FORD(i, a, b) for (auto i = (a) - 1; i >= (b); i--) #define SZ(x) ((int) ((x).size())) #define ALL(x) (x).begin(), (x).end() #define MAXN 200013 typedef long long ll; typedef long double ld; typedef pair<int, int> pii; typedef pair<ll, ll> pll; typedef vector<int> vi; typedef vector<ll> vl; typedef vector<pii> vpi; typedef vector<pll> vpl; int N; pii dp[MAXN]; ordered_set<int> cand; int ans = -1, rec = 0; pii query(int idx) { if (dp[idx] != MP(-1, -1)) return dp[idx]; vi tmp = ask(idx); dp[idx] = {tmp[0], tmp[1]}; if (dp[idx] == MP(0, 0)) ans = idx; return dp[idx]; } int find_best(int n) { // return 0; N = n; if (N == 1) return 0; FOR(i, 0, N) dp[i] = {-1, -1}; int pos = -1; for (int i = 0; i < N && i <= 455; i++) { pii p = query(i); if (ans != -1) return ans; if (pos == -1 || p.fi + p.se > dp[pos].fi + dp[pos].se) pos = i; } rec = dp[pos].fi + dp[pos].se; FOR(i, pos, N) cand.insert(i); //find the last guy that still matches it. // for (int x : cand) // { // cerr << x << ' '; // } // cerr << endl; while(true) { pii p = query(pos); //find the last guy that's == pos int i = 0; for (;; i++) { if ((1 << i) >= SZ(cand)) break; int cur = *cand.find_by_order((1 << i)); pii q = query(cur); if (ans != -1) return ans; // cerr << cur << ' ' << q.fi << ' ' << q.se << endl; if (p != q) break; //find the block that's >= pos } int lo = 0, hi = min(SZ(cand), (1 << i)) - 1; // cerr << lo << ' ' << hi << endl; while(hi > lo) { int mid = (hi + lo + 1) >> 1; int cur = *cand.find_by_order(mid); pii q = query(cur); if (ans != -1) return ans; if (p != q) hi = mid - 1; else lo = mid; } pos = *cand.find_by_order(lo) + 1; FOR(i, 0, lo + 1) { // cerr << "ERASE " << *cand.begin() << endl; cand.erase(cand.begin()); } while(true) { pii p = query(pos); if (ans != -1) return ans; if (p.fi + p.se == rec) break; cand.erase(cand.begin()); pos++; } } //pos is an example of the least worth guy. //so each time you just want to find an example of any guy worth more than it. }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...