제출 #659897

#제출 시각아이디문제언어결과실행 시간메모리
659897peijar드문 곤충 (IOI22_insects)C++17
82.04 / 100
129 ms1060 KiB
#include "insects.h"
#include <bits/stdc++.h>
using namespace std;

set<int> calcInter(set<int> &a, set<int> &b) {
  set<int> ret;
  for (int x : a)
    if (b.count(x))
      ret.insert(x);
  return ret;
}

int min_cardinality(int N) {
  vector<int> roots;
  int nbCC = 0;
  for (int i = 0; i < N; ++i) {
    move_inside(i);
    if (i and press_button() == 2)
      move_outside(i);
    else
      roots.push_back(i), nbCC++;
  }
  vector<bool> isRoot(N);
  for (int r : roots)
    isRoot[r] = true;
  vector<int> toProcess;
  for (int i = 0; i < N; ++i)
    if (!isRoot[i])
      toProcess.push_back(i);
  if (nbCC == 1)
    return N;
  const int TRESH = 5;

  if (nbCC <= (1 << TRESH)) {
    vector<set<int>> withBit(TRESH), withoutBit(TRESH);
    for (int i : roots)
      move_outside(i);
    for (int bit = 0; bit < TRESH; ++bit) {
      for (int i = 0; i < nbCC; ++i) {
        if ((1 << bit) & i)
          move_inside(roots[i]), withBit[bit].insert(roots[i]);
        else
          withoutBit[bit].insert(roots[i]);
      }
      for (int x : toProcess) {
        move_inside(x);
        if (press_button() == 2)
          withBit[bit].insert(x);
        else
          withoutBit[bit].insert(x);
        move_outside(x);
      }
      for (int i = 0; i < nbCC; ++i)
        if ((1 << bit) & i)
          move_outside(roots[i]);
    }
    int ret = N;
    for (int i = 0; i < nbCC; ++i) {
      set<int> cc;
      for (int j = 0; j < N; ++j)
        cc.insert(j);
      for (int bit = 0; bit < TRESH; ++bit) {
        if ((1 << bit) & i)
          cc = calcInter(cc, withBit[bit]);
        else
          cc = calcInter(cc, withoutBit[bit]);
      }
      ret = min(ret, (int)cc.size());
    }
    return ret;
  }

  int lo = 1, up = N / nbCC;
  // invariant : everything outside of toProcess has majority element >= lo
  while (lo < up) {
    int mid = (lo + up + 1) / 2;
    vector<int> kept;
    vector<int> popped;
    for (int i : toProcess) {
      move_inside(i);
      if (press_button() > mid)
        popped.push_back(i), move_outside(i);
      else
        kept.push_back(i);
    }
    int cntPopped = popped.size();
    if (cntPopped == N - nbCC * mid) {
      lo = mid;
      toProcess = move(popped);
    } else {
      up = mid - 1;
      for (int i : kept)
        move_outside(i);
    }
  }
  return lo;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...