Submission #208873

#TimeUsernameProblemLanguageResultExecution timeMemory
208873rama_pangThe Big Prize (IOI17_prize)C++14
100 / 100
58 ms836 KiB
#include "prize.h"

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

map<int, pair<int, int>> memo;
vector<int> query(int i) {
  vector<int> res;
  if (memo.count(i)) {
    res.emplace_back(memo[i].first);
    res.emplace_back(memo[i].second);
  } else {
    res = ask(i);
    memo[i] = {res[0], res[1]};
  }
  return res;
}

int numValuable;
vector<int> candidates; // non-lollipop boxes

void binarySearch(int leftValuable, int rightValuable, int left, int right) {
  if (left > right || leftValuable + rightValuable == numValuable) {
    return;
  }

  int mid = (left + right) / 2;
  vector<int> res = query(mid);
  
  if (res[0] + res[1] == numValuable) { // mid is a lollipop box
    binarySearch(leftValuable, res[1], left, mid - 1);
    binarySearch(res[0], rightValuable, mid + 1, right);
  } else { // mid is a non-lollipop box
    candidates.emplace_back(mid);
    int nearestLeft, nearestRight;

    for (int i = mid + 1; i <= right; i++) {
      res = query(i);
      if (res[0] + res[1] == numValuable) {
        nearestRight = i;
        binarySearch(query(nearestRight)[0], rightValuable, nearestRight + 1, right);
        break;
      } else { // i is a non-lollipop box
        candidates.emplace_back(i);
      }
    }

    for (int i = mid - 1; i >= left; i--) {
      res = query(i);
      if (res[0] + res[1] == numValuable) {
        nearestLeft = i;
        binarySearch(leftValuable, query(nearestLeft)[1], left, nearestLeft - 1);
        break;
      } else { // i is a non-lollipop box
        candidates.emplace_back(i);
      }
    }
  }
}

int find_best(int n) {
  numValuable = 0;
  for (int i = 0; i < min(n, 500); i++) { // least valuable box must satisfy sum^2 <= n, and since n <= 200000 then sum <= 500 will suffice
    vector<int> res = query(i);
    if (res[0] + res[1] > numValuable) {
      numValuable = res[0] + res[1];
    } 
    if (numValuable > 30) { // second least valuable box must satisfy (sum^2)^2 <= n, and since n <= 200000 then sum <= 30 will suffice
      break; // we will only check at most one least valuable box, the rest will be valuable and checked later anyways
    }
  }

  binarySearch(0, 0, 0, n - 1);

  int ans = -1;
  for (auto &c : candidates) {
    vector<int> res = query(c);
    if (res[0] == 0 && res[1] == 0) {
      ans = c;
    }
  }

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