Submission #1335251

#TimeUsernameProblemLanguageResultExecution timeMemory
1335251gohchingjayk드문 곤충 (IOI22_insects)C++20
99.01 / 100
20 ms452 KiB
// Code by meowbert, once again

#include "insects.h"
#include <bits/stdc++.h>
using namespace std;

int min_cardinality(int N) {
    vector<char> inside(N, false), banned(N, false);
    vector<int> reps;
    int species = 0;

    for (int i = 0; i < N; ++i) {
        move_inside(i);
        inside[i] = true;
        if (press_button() > 1) {
            move_outside(i);
            inside[i] = false;
        } else {
            ++species;
            reps.push_back(i);
        }
    }

    vector<pair<int, int>> groups;
    groups.reserve(species);
    for (int i = 0; i < species; ++i) {
        int left = reps[i] + 1;
        int right = (i + 1 < species ? reps[i + 1] - 1 : N - 1);
        groups.push_back({left, right});
    }

    int ans = 1;
    int lo = 2;
    int hi = N / species;
    int last = 1;
    vector<int> added;

    while (lo <= hi) {
        int tgt = lo + (hi - lo) / 3;

        if (tgt < last) {
            for (int i : added) {
                move_outside(i);
                inside[i] = false;
            }
            added.clear();
        }

        int need = species * (tgt - ans);
        int remaining = 0;
        for (int i = 0; i < N; ++i) {
            if (!inside[i] && !banned[i]) {
                ++remaining;
            }
        }

        vector<int> rejected;
        vector<int> ptr(species);
        for (int i = 0; i < species; ++i) {
            ptr[i] = groups[i].first;
        }

        bool progressed = true;
        while ((int)added.size() < need && progressed) {
            if ((int)added.size() + remaining < need) {
                break;
            }
            progressed = false;

            for (int g = 0; g < species; ++g) {
                int right = groups[g].second;
                while (ptr[g] <= right && (inside[ptr[g]] || banned[ptr[g]])) {
                    ++ptr[g];
                }
                if (ptr[g] > right) {
                    continue;
                }

                progressed = true;
                int i = ptr[g]++;
                --remaining;

                move_inside(i);
                inside[i] = true;
                if (press_button() > tgt) {
                    move_outside(i);
                    inside[i] = false;
                    rejected.push_back(i);
                } else {
                    added.push_back(i);
                    if ((int)added.size() == need) {
                        break;
                    }
                }

                if ((int)added.size() + remaining < need) {
                    break;
                }
            }
        }

        last = tgt;
        if ((int)added.size() == need) {
            ans = tgt;
            lo = tgt + 1;
            added.clear();
        } else {
            hi = tgt - 1;
            for (int i : rejected) {
                banned[i] = true;
            }
        }
    }

    return ans;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...