Submission #1225202

#TimeUsernameProblemLanguageResultExecution timeMemory
1225202banganRarest Insects (IOI22_insects)C++20
100 / 100
14 ms476 KiB
#include "insects.h"
#include <bits/stdc++.h>
using namespace std;

const int I_AM_A_BLACK_HOLE = 1;

#define pb push_back
#define MP make_pair

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());

int n;
int unq;
vector<int> in;
vector<int> res;
vector<bool> is_in;
vector<int> save;

pair<bool, int> ok(int k) {
    vector<int> killed;
    while (!res.empty() && k < res.back()) {
        move_outside(in.back());
        killed.pb(in.back());
        is_in[in.back()] = false;
        in.pop_back();
        res.pop_back();
    }
    if (killed.empty()) killed = save;

    vector<int> all = killed;
    shuffle(all.begin(), all.end(), rng);
    for (int i : all) {
        if (is_in[i]) continue;

        move_inside(i);
        int t = press_button();
        if (t > k) move_outside(i);
        else in.pb(i), is_in[i] = true, res.pb(t);
        if (unq * k == in.size()) return MP(true, 0);
    }

    if (unq * k == in.size()) return MP(true, 0);
    else {
        save = in;
        return MP(false, in.size() / unq);
    }
}

int min_cardinality(int N) {
    is_in.resize(N);
    for (int i = 0; i < N; i++) {
        save.pb(i);
        move_inside(i);
        int t = press_button();
        if (t == 2) move_outside(i);
        else in.pb(i), is_in[i] = true, res.pb(t);
    }
    unq = in.size();

    if (unq == 1) return N;
    if (unq == N) return 1;

    if (unq <= I_AM_A_BLACK_HOLE) {
        while (!in.empty()) {
            move_outside(in.back());
            is_in[in.back()] = false;
            in.pop_back();
        }

        vector<int> all;
        for (int i=0; i<N; i++) all.pb(i);

        unq--;
        int ans = N;
        while (unq--) {
            vector<int> rem;
            int cur = 0;
            shuffle(all.begin(), all.end(), rng);
            while (!all.empty()) {
                int i = all.back();
                all.pop_back();
                move_inside(i);
                int res = press_button();
                if (res == cur) {
                    move_outside(i);
                    rem.pb(i);
                }
                else {
                    in.pb(i);
                }
                cur = res;
            }
            ans = min(ans, cur);
            if (ans == 1) return 1;
            all = rem;
            while (!in.empty()) {
                move_outside(in.back());
                in.pop_back();
            }
        }
        return min((int) all.size(), ans);
    }

    n = N;
    int l = 1, r = n / unq;
    while (l != r) {
        int mid = (l+r+1) / 2;
        auto [can, lim] = ok(mid);
        if (can) l = mid;
        else r = min(mid - 1, lim);
    }
    return l;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...