Submission #798507

# Submission time Handle Problem Language Result Execution time Memory
798507 2023-07-30T19:18:42 Z jakobrs Radio Towers (IOI22_towers) C++17
0 / 100
786 ms 24012 KB
#include <optional>
#include <unordered_set>
#include <vector>
#include <algorithm>

#ifndef EVAL
#include <format>
#include <iostream>

template <typename... Args>
void print(std::format_string<Args...> fmt, Args &&...args) {
  std::cerr << std::format(fmt, std::forward<Args>(args)...);
}

template <typename... Args>
void println(std::format_string<Args...> fmt, Args &&...args) {
  std::cerr << std::format(fmt, std::forward<Args>(args)...) << '\n';
}
#else
template <typename... T> void print(T &&...args) {}
template <typename... T> void println(T &&...args) {}
#endif

int n;
std::vector<int> h;

void init(int N, std::vector<int> H) {
  n = N;
  h = H;
}

template <typename Node> struct SegmentTree {
  std::vector<Node> nodes;
  int offset;

  explicit SegmentTree(int sz) : nodes(2 * sz), offset(sz) {}

  void update(int idx, const Node &node) {
    idx += offset;
    nodes[idx] = node;

    while (idx /= 2) {
      nodes[idx] = nodes[2 * idx] * nodes[2 * idx + 1];
    }
  }

  Node query(int l, int r) const {
    Node left, right;

    l += offset;
    r += offset;

    while (l < r) {
      if (l & 1)
        left = left * nodes[l++];
      if (r & 1)
        right = nodes[--r] * right;

      l >>= 1;
      r >>= 1;
    }

    return left * right;
  }
};

int d;

struct LeftNode {
  int a, b, min, max;

  LeftNode() : a(-1), b(-1), min(2'000'000'000), max(-2'000'000'000) {}
  LeftNode(int a) : a(-1), b(-1), min(a), max(a) {}
  LeftNode(int a, int b, int min, int max) : a(a), b(b), min(min), max(max) {}

  LeftNode operator*(const LeftNode &rhs) const {
    std::pair<int, int> c1 = {b, a};
    std::pair<int, int> c2 = {rhs.b, rhs.a};
    std::pair<int, int> c3 = {-1, -1};
    if (rhs.max >= 0 && rhs.max - min >= d) {
      c3 = {rhs.max, min};
    }

    std::pair<int, int> best = std::max(std::max(c1, c2), c3);

    return {best.second, best.first, std::min(min, rhs.min),
            std::max(max, rhs.max)};
  }
};
struct RightNode {
  int a, b, min, max;

  RightNode() : a(-1), b(-1), min(2'000'000'000), max(-2'000'000'000) {}
  RightNode(int a) : a(-1), b(-1), min(a), max(a) {}
  RightNode(int a, int b, int min, int max) : a(a), b(b), min(min), max(max) {}

  RightNode operator*(const RightNode &rhs) const {
    std::pair<int, int> c1 = {b, a};
    std::pair<int, int> c2 = {rhs.b, rhs.a};
    std::pair<int, int> c3 = {-1, -1};
    if (max >= 0 && max - rhs.min >= d) {
      c3 = {max, rhs.min};
    }

    std::pair<int, int> best = std::max(std::max(c1, c2), c3);

    return {best.second, best.first, std::min(min, rhs.min),
            std::max(max, rhs.max)};
  }
};

struct PrecomputedData {
  std::unordered_set<int> included_s;
  std::vector<int> prefix_sums, prev, next;

  SegmentTree<LeftNode> left_st;
  SegmentTree<RightNode> right_st;
};

std::optional<PrecomputedData> precomputed;

int max_towers(int L, int R, int D) {
  if (L == R)
    return 1;
  R += 1;

  if (!precomputed) {
    d = D;
    std::vector<int> included{h[0]};
    int intermediary = h[0];
    for (int i = 1; i < n; i++) {
      if (h[i] > intermediary) {
        // println("Found new intermediary: {}", h[i]);
        intermediary = h[i];
      } else if (intermediary - included.back() < D) {
        if (h[i] < included.back()) {
          // println("Found better tower: {} instead of {}", h[i],
          // included.back());
          included.pop_back();
          included.push_back(h[i]);
          intermediary = h[i];
        } else {
          // println("Found new tower, but it's worse: {} instead of {}",
          // h[i], included.back());
        }
      } else if (intermediary - h[i] >= D) {
        // println("Found new tower: {} (previous was {}, greatest: {})",
        // h[i], included.back(), greatest);
        included.push_back(h[i]);
        intermediary = h[i];
      }
    }

    std::unordered_set<int> included_s(included.begin(), included.end());

    std::vector<int> prev, next;
    int prev_val = -1;
    for (int i = 0; i < n; i++) {
      if (included_s.count(h[i])) {
        prev_val = i;
      }
      prev.push_back(prev_val);
    }
    int next_val = -1;
    for (int i = n - 1; i >= 0; i--) {
      if (included_s.count(h[i])) {
        next_val = i;
      }
      next.push_back(next_val);
    }
    std::reverse(next.begin(), next.end());
    std::vector<int> prefix_sums{1};
    prefix_sums.reserve(n + 1);
    for (int i = 0; i < n; i++) {
      prefix_sums.push_back(prefix_sums.back() + included_s.count(h[i]));
    }

    int o = 1;
    while (o < n)
      o *= 2;

    SegmentTree<LeftNode> left_st(o);
    SegmentTree<RightNode> right_st(o);

    for (int i = 0; i < n; i++) {
      left_st.update(i, LeftNode(h[i]));
      right_st.update(i, RightNode(h[i]));
    }

    precomputed = std::make_optional(PrecomputedData{
        included_s, prefix_sums, prev, next, left_st, right_st});
  }

  int total = precomputed->prefix_sums[R] - precomputed->prefix_sums[L];

  int next = precomputed->next[L];
  auto q0 = precomputed->left_st.query(L, next);
  if (q0.b - h[next] >= D) {
    total += 1;
  }

  int prev = precomputed->prev[R - 1];
  auto q1 = precomputed->right_st.query(prev + 1, R);
  if (q1.b - h[prev] >= D) {
    total += 1;
  }

  return total;
}
# Verdict Execution time Memory Grader output
1 Incorrect 377 ms 10332 KB 11th lines differ - on the 1st token, expected: '1', found: '0'
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 0 ms 336 KB Output is correct
2 Correct 1 ms 592 KB Output is correct
3 Correct 1 ms 592 KB Output is correct
4 Correct 1 ms 624 KB Output is correct
5 Correct 1 ms 592 KB Output is correct
6 Correct 1 ms 592 KB Output is correct
7 Correct 1 ms 592 KB Output is correct
8 Incorrect 1 ms 592 KB 1st lines differ - on the 1st token, expected: '1', found: '0'
9 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 0 ms 336 KB Output is correct
2 Correct 1 ms 592 KB Output is correct
3 Correct 1 ms 592 KB Output is correct
4 Correct 1 ms 624 KB Output is correct
5 Correct 1 ms 592 KB Output is correct
6 Correct 1 ms 592 KB Output is correct
7 Correct 1 ms 592 KB Output is correct
8 Incorrect 1 ms 592 KB 1st lines differ - on the 1st token, expected: '1', found: '0'
9 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 588 ms 22476 KB Output is correct
2 Correct 634 ms 22620 KB Output is correct
3 Correct 682 ms 22592 KB Output is correct
4 Correct 786 ms 23944 KB Output is correct
5 Correct 718 ms 23936 KB Output is correct
6 Correct 766 ms 24012 KB Output is correct
7 Correct 511 ms 24000 KB Output is correct
8 Incorrect 662 ms 19716 KB 1st lines differ - on the 1st token, expected: '1', found: '0'
9 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Incorrect 222 ms 5736 KB 2nd lines differ - on the 1st token, expected: '7063', found: '7197'
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 0 ms 336 KB Output is correct
2 Correct 1 ms 592 KB Output is correct
3 Correct 1 ms 592 KB Output is correct
4 Correct 1 ms 624 KB Output is correct
5 Correct 1 ms 592 KB Output is correct
6 Correct 1 ms 592 KB Output is correct
7 Correct 1 ms 592 KB Output is correct
8 Incorrect 1 ms 592 KB 1st lines differ - on the 1st token, expected: '1', found: '0'
9 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Incorrect 377 ms 10332 KB 11th lines differ - on the 1st token, expected: '1', found: '0'
2 Halted 0 ms 0 KB -