Alex's Anthology of Algorithms Common Code for Contests in Concise C++
Optimization / Binary Search

Finds the first value where a monotone Boolean predicate becomes true when an upper bound is not known in advance. Exponential search first grows the search range by powers of two until it brackets the transition point, then finishes with ordinary binary search.

This is useful for answer-search problems over unbounded or very large integer domains.

Overflow warning: The predicate must become true before the exponentially growing probe overflows Int; otherwise, add an explicit limit.

  • exponential_first_true(lo, pred) returns the smallest integer x greater than or equal to lo such that pred(x) is true.

Implementation

#include <cstdint>

template<typename Int, typename Pred>
Int exponential_first_true(Int lo, Pred pred) {  // 000[1]11
  if (pred(lo)) {
    return lo;
  }
  Int step = 1;
  while (!pred(lo + step)) {
    step *= 2;
  }
  Int hi = lo + step;
  lo += step / 2;
  while (lo < hi) {
    Int mid = lo + (hi - lo) / 2;
    if (pred(mid)) {
      hi = mid;
    } else {
      lo = mid + 1;
    }
  }
  return lo;
}

Example Usage

#include <cassert>

int main() {
  auto at_least_1000 = [](int x) { return x >= 1000; };
  assert(exponential_first_true(1000, at_least_1000) == 1000);
  assert(exponential_first_true(0, at_least_1000) == 1000);
  assert(exponential_first_true(5, at_least_1000) == 1000);
  auto square_large_enough = [](int64_t x) { return x * x >= 123456789LL; };
  assert(exponential_first_true(0LL, square_large_enough) == 11112);
  return 0;
}