Submission #361562

#TimeUsernameProblemLanguageResultExecution timeMemory
361562KoDThe Big Prize (IOI17_prize)C++17
0 / 100
14 ms9964 KiB
#include "prize.h"
#include <vector>
#include <utility>
#include <algorithm>
#include <queue>
#include <set>
#include <cassert>
 
template <class T>
using Vec = std::vector<T>;
 
int find_best(int N) {
  Vec<Vec<int>> memo(N);
  const auto query = [&](const int i) -> const Vec<int>& {
    if (memo[i].empty()) {
      memo[i] = ask(i);
    }
    return memo[i];
  };
  int max = 0;
  const auto L = std::min(N, 475);
  for (int i = 0; i < L; ++i) {
    max = std::max(max, query(i)[0] + query(i)[1]);
    if (max > 26) {
      break;
    }
    assert(i < 300);
  }
  std::set<int> pos;
  for (int i = 0; i < L; ++i) {
    if (query(i)[0] + query(i)[1] < max) {
      pos.insert(i);
      if (query(i)[0] + query(i)[1] == 0) {
        return i;
      }
    }
  }
  std::queue<std::pair<int, int>> que;
  que.emplace(L, N - 1);
  Vec<int> left_count(N + 1, -1);
  left_count[N] = max;
  left_count[L - 1] = (int) pos.size();
  const auto count = [&](const int l, const int r) {
    return (left_count[r + 1] == -1 ? query(r + 1)[0] : left_count[r + 1]) - (left_count[l - 1] == -1 ? query(l - 1)[0] : left_count[l - 1]);
  };
  while (!que.empty() && (int) pos.size() < max) {
    const auto [l, r] = que.front();
    que.pop();
    if (l > r) {
      continue;
    }
    if (count(l, r) == 0) {
      continue;
    }
    const auto mid = (l + r) / 2;
    auto nr = mid - 1;
    auto nl = mid;
    while (nl <= r) {
      if (query(nl)[0] + query(nl)[1] == max) {
        break;
      }
      else {
        pos.insert(nl);
        if (query(nl)[0] + query(nl)[1] == 0) {
          return nl;
        }
        nl += 1;
      }
    }
    if (nl == r + 1) {
      while (nr >= l) {
        if (query(nr)[0] + query(nr)[1] == max) {
          break;
        }
        else {
          pos.insert(nr);
          if (query(nr)[0] + query(nr)[1] == 0) {
            return nr;
          }
          nr -= 1;
        }
      }
      que.emplace(l, nr - 1);
    }
    else {
      left_count[mid] = query(nl)[0] - (nl - mid);
      que.emplace(l, mid - 1);
      que.emplace(nl + 1, r);
    }
  } 
  for (const auto x: pos) {
    if (query(x)[0] + query(x)[1] == 0) {
      return x;
    }
  }
  return -1;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...