Submission #1252148

#TimeUsernameProblemLanguageResultExecution timeMemory
1252148jerryObstacles for a Llama (IOI25_obstacles)C++20
Compilation error
0 ms0 KiB
#include <assert.h>
#include <utility>
#include <vector>

class SegmentTree {
  public:
    SegmentTree(const std::vector<int>& data);

    int query_max(int l, int r) const;  // include-exclude
    int get_next_le(int from, int value) const;
    int get_prev_gt(int from, int value) const;

  private:
    int n;
    std::vector<int> max, min;
};

class SingleSideSolver {
  public:
    SingleSideSolver(const std::vector<int>& _t, const std::vector<int>& _h);

    bool can_reach(int l, int s, int d) const;

  private:
    int get_strictest_column(int l, int r) const;
    int get_leftmost_reachable_column(int s, int l) const;
    bool reduce_columns(const std::vector<int>& idxs) const;

    const std::vector<int> t, h;
    const SegmentTree row_tree, col_tree;
};

std::unique_ptr<SingleSideSolver> left, right;
int n, m;

void initialize(std::vector<int> t, std::vector<int> h) {
  n = t.size();
  m = h.size();
  left = std::make_unique<SingleSideSolver>(t, h);
  right = std::make_unique<SingleSideSolver>(t, std::vector<int>(h.rbegin(), h.rend()));
}

bool can_reach(int l, int r, int s, int d) {
  return left->can_reach(l, s, d) && right->can_reach(m - r - 1, m - s - 1, m - d - 1);
}

SegmentTree::SegmentTree(const std::vector<int>& data) {
  n = data.size() + 1;
  while (__builtin_popcount(n) > 1)
    n += n & -n;

  max = std::vector<int>(n * 2, INT_MAX);
  min = std::vector<int>(n * 2, INT_MIN);
  for (int i = 0; i < data.size(); i++)
    max[i + n] = min[i + n] = data[i];
  for (int i = n - 1; i > 0; i--) {
    max[i] = std::max(max[i * 2], max[i * 2 + 1]);
    min[i] = std::min(min[i * 2], min[i * 2 + 1]);
  }
}

int SegmentTree::query_max(int l, int r) const {
  int answer = INT_MIN;
  for (l += n, r += n; l != r; l /= 2, r /= 2) {
    if (l & 1)
      answer = std::max(answer, max[l++]);
    if (r & 1)
      answer = std::max(answer, max[--r]);
  }
  return answer;
}

int SegmentTree::get_next_le(int from, int value) const {
  from += n;
  while (min[from] > value) {
    if (from % 2 == 0)
      while (from % 2 == 0)
        from /= 2;
    else
      from++;
  }
  while (from < n) {
    from *= 2;
    if (min[from] > value)
      from++;
  }
  return from - n;
}

int SegmentTree::get_prev_gt(int from, int value) const {
  if (query_max(0, from + 1) <= value)
    return -1;
  from += n;
  while (max[from] <= value) {
    if (from % 2 == 1)
      while (from % 2 == 1)
        from /= 2;
    else
      from--;
  }
  while (from < n) {
    from *= 2;
    if (max[from + 1] > value)
      from++;
  }
  return from - n;
}

SingleSideSolver::SingleSideSolver(const std::vector<int>& _t, const std::vector<int>& _h)
  : t(_t), h(_h), row_tree(t), col_tree(h) {}

bool SingleSideSolver::can_reach(int l, int s, int d) const {
  const int col = get_leftmost_reachable_column(s, l);
  const int c1 = get_strictest_column(col, s);
  const int c2 = get_strictest_column(col, d);
  return reduce_columns({s, c1, col, c2, d});
}

int SingleSideSolver::get_strictest_column(int l, int r) const {
  return col_tree.query_max(l, r + 1);
}

int SingleSideSolver::get_leftmost_reachable_column(int s, int l) const {
  int lo = l - 1, hi = s;
  while (lo + 1 < hi) {
    const int mid = (lo + hi) / 2;
    const int c = get_strictest_column(mid, s);
    if (reduce_columns({s, c, mid}))
      hi = mid;
    else
      lo = mid;
  }
  return hi;
}

bool SingleSideSolver::reduce_columns(const std::vector<int>& idxs) const {
  assert(t[0] > h[idxs[0]]);

  int max_depth = 0;
  for (int i : idxs) {
    if (t[max_depth] > h[i])
      max_depth = row_tree.get_next_le(max_depth, h[i]) - 1;
    else
      max_depth = row_tree.get_prev_gt(max_depth, h[i]);
    if (max_depth < 0)
      return false;
  }
  return true;
}

Compilation message (stderr)

obstacles.cpp:33:6: error: 'unique_ptr' in namespace 'std' does not name a template type
   33 | std::unique_ptr<SingleSideSolver> left, right;
      |      ^~~~~~~~~~
obstacles.cpp:4:1: note: 'std::unique_ptr' is defined in header '<memory>'; did you forget to '#include <memory>'?
    3 | #include <vector>
  +++ |+#include <memory>
    4 | 
obstacles.cpp: In function 'void initialize(std::vector<int>, std::vector<int>)':
obstacles.cpp:39:3: error: 'left' was not declared in this scope
   39 |   left = std::make_unique<SingleSideSolver>(t, h);
      |   ^~~~
obstacles.cpp:39:15: error: 'make_unique' is not a member of 'std'
   39 |   left = std::make_unique<SingleSideSolver>(t, h);
      |               ^~~~~~~~~~~
obstacles.cpp:39:15: note: 'std::make_unique' is defined in header '<memory>'; did you forget to '#include <memory>'?
obstacles.cpp:39:43: error: expected primary-expression before '>' token
   39 |   left = std::make_unique<SingleSideSolver>(t, h);
      |                                           ^
obstacles.cpp:40:3: error: 'right' was not declared in this scope
   40 |   right = std::make_unique<SingleSideSolver>(t, std::vector<int>(h.rbegin(), h.rend()));
      |   ^~~~~
obstacles.cpp:40:16: error: 'make_unique' is not a member of 'std'
   40 |   right = std::make_unique<SingleSideSolver>(t, std::vector<int>(h.rbegin(), h.rend()));
      |                ^~~~~~~~~~~
obstacles.cpp:40:16: note: 'std::make_unique' is defined in header '<memory>'; did you forget to '#include <memory>'?
obstacles.cpp:40:44: error: expected primary-expression before '>' token
   40 |   right = std::make_unique<SingleSideSolver>(t, std::vector<int>(h.rbegin(), h.rend()));
      |                                            ^
obstacles.cpp: In function 'bool can_reach(int, int, int, int)':
obstacles.cpp:44:10: error: 'left' was not declared in this scope
   44 |   return left->can_reach(l, s, d) && right->can_reach(m - r - 1, m - s - 1, m - d - 1);
      |          ^~~~
obstacles.cpp:44:38: error: 'right' was not declared in this scope
   44 |   return left->can_reach(l, s, d) && right->can_reach(m - r - 1, m - s - 1, m - d - 1);
      |                                      ^~~~~
obstacles.cpp: In constructor 'SegmentTree::SegmentTree(const std::vector<int>&)':
obstacles.cpp:52:33: error: 'INT_MAX' was not declared in this scope
   52 |   max = std::vector<int>(n * 2, INT_MAX);
      |                                 ^~~~~~~
obstacles.cpp:4:1: note: 'INT_MAX' is defined in header '<climits>'; did you forget to '#include <climits>'?
    3 | #include <vector>
  +++ |+#include <climits>
    4 | 
obstacles.cpp:53:33: error: 'INT_MIN' was not declared in this scope
   53 |   min = std::vector<int>(n * 2, INT_MIN);
      |                                 ^~~~~~~
obstacles.cpp:53:33: note: 'INT_MIN' is defined in header '<climits>'; did you forget to '#include <climits>'?
obstacles.cpp: In member function 'int SegmentTree::query_max(int, int) const':
obstacles.cpp:63:16: error: 'INT_MIN' was not declared in this scope
   63 |   int answer = INT_MIN;
      |                ^~~~~~~
obstacles.cpp:63:16: note: 'INT_MIN' is defined in header '<climits>'; did you forget to '#include <climits>'?