Submission #793346

#TimeUsernameProblemLanguageResultExecution timeMemory
793346PixelCatScales (IOI15_scales)C++14
100 / 100
10 ms412 KiB
#ifdef NYAOWO #include "grader.cpp" #endif #include "scales.h" #include <bits/stdc++.h> #define For(i, a, b) for(int i = a; i <= b; i++) #define Forr(i, a, b) for(int i = a; i >= b; i--) #define F first #define S second #define all(x) x.begin(), x.end() #define sz(x) ((int)x.size()) #define eb emplace_back using namespace std; using LL = long long; using pii = pair<int, int>; using BS = bitset<720>; int W[] = {1, 2, 3, 4, 5, 6}; mt19937_64 rng(7456); uint64_t seed; // 0 for lightest, 1 for median, 2 for heaviest, 3 for next lightest vector<vector<int>> perm; vector<vector<int>> options; vector<BS> mask[4]; bool match(const vector<int> &ord, const vector<int> &opt, int res) { if(opt[0] == 0) { bool ok = true; For(i, 1, 3) ok = ok && (ord[opt[i]] >= ord[opt[res]]); return ok; } if(opt[0] == 2) { bool ok = true; For(i, 1, 3) ok = ok && (ord[opt[i]] <= ord[opt[res]]); return ok; } if(opt[0] == 1) { int owo = 0; For(i, 1, 3) { int dif = (ord[opt[i]] - ord[opt[res]]); if(dif < 0) owo |= 1; if(dif == 0) owo |= 2; if(dif > 0) owo |= 4; } return owo == 7; } if(opt[0] == 3) { int o[3] = {opt[1], opt[2], opt[3]}; sort(o, o + 3, [&](int x, int y){return ord[x] < ord[y];}); int idx = 0; if(ord[opt[4]] > ord[o[2]]) idx = 0; else if(ord[opt[4]] > ord[o[1]]) idx = 2; else if(ord[opt[4]] > ord[o[0]]) idx = 1; idx = o[idx]; if(idx == opt[1]) idx = 1; else if(idx == opt[2]) idx = 2; else if(idx == opt[3]) idx = 3; return idx == res; } return false; } // how many possibilities remain at most? int worstmatch(const BS &alive, const int &opt) { int mx = 0; For(res, 1, 3) { mx = max(mx, (int) (alive & mask[res][opt]).count()); } return mx; } int best_opt(const BS &alive) { int mx = 1000, idx = -1; vector<int> all_opt; For(i, 0, sz(options) - 1) all_opt.eb(i); shuffle(all(all_opt), rng); // auto start = clock(); for(auto &i:all_opt) { int k = worstmatch(alive, i); if(k < mx) { mx = k; idx = i; } } // auto stop = clock(); // cerr << fixed << setprecision(3); // cerr << "elapsed: " << (double)(stop - start) / CLOCKS_PER_SEC << "\n"; return idx; } int make_query(const vector<int> &opt) { int x = -1; if(opt[0] == 0) { x = getLightest(opt[1] + 1, opt[2] + 1, opt[3] + 1); } else if(opt[0] == 1) { x = getMedian(opt[1] + 1, opt[2] + 1, opt[3] + 1); } else if(opt[0] == 2) { x = getHeaviest(opt[1] + 1, opt[2] + 1, opt[3] + 1); } else if(opt[0] == 3) { x = getNextLightest(opt[1] + 1, opt[2] + 1, opt[3] + 1, opt[4] + 1); } For(i, 1, 3) if(x == opt[i] + 1) return i; assert(false); return -1; } void remove_impossible(BS &alive, const int &opt, int res) { alive &= mask[res][opt]; } // #define TESTING #ifdef TESTING int test_all(int lim) { map<int, int> cnt; // {# of queries, count} For(i, 0, 719) { For(j, 0, 5) W[j] = perm[i][j] + 1; _setNewTest(W); orderCoins(); cnt[_numQueries]++; if(cnt[7] >= lim) return lim; } // for(auto &i:cnt) cerr << i.F << ": " << i.S << "\n"; return cnt[7]; } uint64_t find_seed() { int mn = 120, mni = 48763; For(s, 408, 20000) { seed = s; int k = test_all(mn); if(k < mn) { mn = k; mni = s; cerr << s << " " << k << "\n"; } if(s % 300 == 299) cerr << "progress: " << (s + 1) << "\n"; } return mni; } #endif void init(int T) { seed = 3179; assert(T < 20); int a[6] = {0, 1, 2, 3, 4, 5}; perm.clear(); do { perm.eb(a, a + 6); } while(next_permutation(a, a + 6)); For(i, 0, 5) For(j, i + 1, 5) For(k, j + 1, 5) { options.push_back({0, i, j, k}); options.push_back({1, i, j, k}); options.push_back({2, i, j, k}); For(l, 0, 5) { if(i == l || j == l || k == l) continue; options.push_back({3, i, j, k, l}); } } For(r, 1, 3) mask[r].clear(); for(auto &opt:options) For(r, 1, 3) { mask[r].eb(); mask[r].back().reset(); For(i, 0, 719) if(match(perm[i], opt, r)) mask[r].back()[i] = 1; } cerr << sz(perm) << "\n"; cerr << sz(options) << "\n"; #ifdef TESTING // test_all(); find_seed(); #endif } void orderCoins() { rng.seed(seed); BS alive; For(i, 0, 719) alive[i] = 1; while(alive.count() > 1) { int k = best_opt(alive); int r = make_query(options[k]); remove_impossible(alive, k, r); // cout << sz(alive) << " " << k << " " << r << "\n" << flush; } int pos = -1; For(i, 0, 719) if(alive[i]) pos = i; vector<int> &ord = perm[pos]; For(i, 0, 5) W[ord[i]] = i + 1; #ifndef TESTING answer(W); #endif }
#Verdict Execution timeMemoryGrader output
Fetching results...