library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub maspypy/library

:heavy_check_mark: ds/segtree/dynamic_segtree.hpp

Depends on

Verified with

Code

#include "ds/node_pool.hpp"

// sparse もあるので状況によってはそっちで
template <typename Monoid, bool PERSISTENT>
struct Dynamic_SegTree {
  using MX = Monoid;
  using X = typename MX::value_type;
  using F = function<X(ll, ll)>;
  F default_prod;

  struct Node {
    Node *l, *r;
    X x;
  };

  const ll L0, R0;
  Node_Pool<Node> pool;
  using np = Node *;

  Dynamic_SegTree(
      ll L0, ll R0, F default_prod = [](ll l, ll r) -> X { return MX::id(); })
      : default_prod(default_prod), L0(L0), R0(R0) {}

  np new_root() { return new_node(L0, R0); }

  np new_node(const X x) {
    np n = pool.create();
    n->l = nullptr, n->r = nullptr, n->x = x;
    return n;
  }

  np new_node(ll l, ll r) { return new_node(default_prod(l, r)); }
  np new_node() { return new_node(L0, R0); }

  np new_node(const vc<X> &dat) {
    assert(L0 == 0 && R0 == len(dat));
    auto dfs = [&](auto &dfs, ll l, ll r) -> np {
      if (l == r) return nullptr;
      if (r == l + 1) return new_node(dat[l]);
      ll m = (l + r) / 2;
      np l_root = dfs(dfs, l, m), r_root = dfs(dfs, m, r);
      X x = MX::op(l_root->x, r_root->x);
      np root = new_node(x);
      root->l = l_root, root->r = r_root;
      return root;
    };
    return dfs(dfs, 0, len(dat));
  }

  X prod(np root, ll l, ll r) {
    assert(L0 <= l && l <= r && r <= R0);
    if (!root || l == r) return MX::id();
    X x = MX::id();
    prod_rec(root, L0, R0, l, r, x);
    return x;
  }

  np set(np root, ll i, const X &x) {
    assert(root && L0 <= i && i < R0);
    root = (root ? copy_node(root) : new_node());
    set_rec(root, L0, R0, i, x);
    return root;
  }

  np multiply(np root, ll i, const X &x) {
    assert(root && L0 <= i && i < R0);
    root = (root ? copy_node(root) : new_node());
    multiply_rec(root, L0, R0, i, x);
    return root;
  }

  template <typename F>
  ll max_right(np root, F check, ll L) {
    assert(root && L0 <= L && L <= R0 && check(MX::id()));
    X x = MX::id();
    return max_right_rec(root, check, L0, R0, L, x);
  }

  template <typename F>
  ll min_left(np root, F check, ll R) {
    assert(L0 <= R && R <= R0 && check(MX::id()));
    X x = MX::id();
    return min_left_rec(root, check, L0, R0, R, x);
  }

  // (idx, val)
  template <typename F>
  void enumerate(np root, F f) {
    if (!root) return;
    auto dfs = [&](auto &dfs, np c, ll l, ll r) -> void {
      if (!c) return;
      if (r - l == 1) {
        f(l, c->x);
        return;
      }
      ll m = (l + r) / 2;
      dfs(dfs, c->l, l, m);
      dfs(dfs, c->r, m, r);
    };
    dfs(dfs, root, L0, R0);
    return;
  }

  void reset() { pool.reset(); }

 private:
  np copy_node(np c) {
    if (!c || !PERSISTENT) return c;
    np n = pool.create();
    n->l = c->l, n->r = c->r, n->x = c->x;
    return n;
  }

  void set_rec(np c, ll l, ll r, ll i, const X &x) {
    assert(c);
    // もう c は新しくしてある
    if (r == l + 1) {
      c->x = x;
      return;
    }
    ll m = (l + r) / 2;
    if (l <= i && i < m) {
      c->l = (c->l ? copy_node(c->l) : new_node());
      set_rec(c->l, l, m, i, x);
    }
    if (m <= i && i < r) {
      c->r = (c->r ? copy_node(c->r) : new_node());
      set_rec(c->r, m, r, i, x);
    }
    X xl = (c->l ? c->l->x : default_prod(l, m));
    X xr = (c->r ? c->r->x : default_prod(m, r));
    c->x = MX::op(xl, xr);
    return;
  }

  void multiply_rec(np c, ll l, ll r, ll i, const X &x) {
    assert(c);
    // もう c は新しくしてある
    if (r == l + 1) {
      c->x = MX::op(c->x, x);
      return;
    }
    ll m = (l + r) / 2;
    if (l <= i && i < m) {
      c->l = (c->l ? copy_node(c->l) : new_node());
      multiply_rec(c->l, l, m, i, x);
    }
    if (m <= i && i < r) {
      c->r = (c->r ? copy_node(c->r) : new_node());
      multiply_rec(c->r, m, r, i, x);
    }
    X xl = (c->l ? c->l->x : default_prod(l, m));
    X xr = (c->r ? c->r->x : default_prod(m, r));
    c->x = MX::op(xl, xr);
    return;
  }

  void prod_rec(np c, ll l, ll r, ll ql, ll qr, X &x) {
    chmax(ql, l);
    chmin(qr, r);
    if (ql >= qr) return;
    if (!c) {
      x = MX::op(x, default_prod(ql, qr));
      return;
    }
    if (l == ql && r == qr) {
      x = MX::op(x, c->x);
      return;
    }
    ll m = (l + r) / 2;
    prod_rec(c->l, l, m, ql, qr, x);
    prod_rec(c->r, m, r, ql, qr, x);
  }

  // これ new node 作ってるのはさぼり
  template <typename F>
  ll max_right_rec(np c, const F &check, ll l, ll r, ll ql, X &x) {
    if (r <= ql) return R0;
    if (ql <= l && check(MX::op(x, c->x))) {
      x = MX::op(x, c->x);
      return R0;
    }
    if (r == l + 1) return l;
    ll m = (l + r) / 2;
    if (!c->l) c->l = new_node(l, m);
    ll k = max_right_rec(c->l, check, l, m, ql, x);
    if (k != R0) return k;
    if (!c->r) c->r = new_node(m, r);
    return max_right_rec(c->r, check, m, r, ql, x);
  }

  // これ new node 作ってるのはさぼり
  template <typename F>
  ll min_left_rec(np c, const F &check, ll l, ll r, ll qr, X &x) {
    if (qr <= l) return L0;
    if (r <= qr && check(MX::op(c->x, x))) {
      x = MX::op(x, c->x);
      return L0;
    }
    if (r == l + 1) return r;
    ll m = (l + r) / 2;
    if (!c->r) c->r = new_node(m, r);
    ll k = min_left_rec(c->r, check, m, r, qr, x);
    if (k != L0) return k;
    if (!c->l) c->l = new_node(l, m);
    return min_left_rec(c->l, check, l, m, qr, x);
  }
};
#line 1 "ds/segtree/dynamic_segtree.hpp"

#line 1 "ds/node_pool.hpp"
// マルチテストケースでも確保済み chunk を再利用する
template <class Node>
struct Node_Pool {
  union Slot {
    Node node;
    Slot* next;

    Slot() {}
    ~Slot() {}
  };
  using np = Node*;

  static constexpr int CHUNK_SIZE = 1 << 12;

  vc<unique_ptr<Slot[]>> chunks;
  int chunk_id = 0;
  int pos = 0;
  Slot* free_head = nullptr;

  ~Node_Pool() {
    auto& cache = chunk_cache();
    for (auto& p : chunks) cache.eb(std::move(p));
  }

  template <class... Args>
  np create(Args&&... args) {
    Slot* s = new_slot();
    return ::new (&s->node) Node(forward<Args>(args)...);
  }

  np clone(const np x) {
    assert(x);
    Slot* s = new_slot();
    return ::new (&s->node) Node(*x);
  }

  void destroy(np x) {
    if (!x) return;
    x->~Node();
    Slot* s = reinterpret_cast<Slot*>(x);
    s->next = free_head;
    free_head = s;
  }

  // 全 node を無効化する。
  // 確保済み chunk は解放せず、次回以降に再利用する。
  void reset() {
    free_head = nullptr;
    chunk_id = 0;
    pos = 0;
  }

 private:
  static vc<unique_ptr<Slot[]>>& chunk_cache() {
    // static Node_Pool の destructor より先に破棄されないようにする。
    static auto* cache = new vc<unique_ptr<Slot[]>>();
    return *cache;
  }

  void alloc_chunk() {
    auto& cache = chunk_cache();
    if (cache.empty()) {
      chunks.eb(make_unique<Slot[]>(CHUNK_SIZE));
    } else {
      chunks.eb(std::move(cache.back()));
      cache.pop_back();
    }
  }

  Slot* new_slot() {
    if (free_head) {
      Slot* s = free_head;
      free_head = free_head->next;
      return s;
    }

    if (chunk_id == len(chunks)) alloc_chunk();

    Slot* s = &chunks[chunk_id][pos++];
    if (pos == CHUNK_SIZE) {
      ++chunk_id;
      pos = 0;
    }
    return s;
  }
};
#line 3 "ds/segtree/dynamic_segtree.hpp"

// sparse もあるので状況によってはそっちで
template <typename Monoid, bool PERSISTENT>
struct Dynamic_SegTree {
  using MX = Monoid;
  using X = typename MX::value_type;
  using F = function<X(ll, ll)>;
  F default_prod;

  struct Node {
    Node *l, *r;
    X x;
  };

  const ll L0, R0;
  Node_Pool<Node> pool;
  using np = Node *;

  Dynamic_SegTree(
      ll L0, ll R0, F default_prod = [](ll l, ll r) -> X { return MX::id(); })
      : default_prod(default_prod), L0(L0), R0(R0) {}

  np new_root() { return new_node(L0, R0); }

  np new_node(const X x) {
    np n = pool.create();
    n->l = nullptr, n->r = nullptr, n->x = x;
    return n;
  }

  np new_node(ll l, ll r) { return new_node(default_prod(l, r)); }
  np new_node() { return new_node(L0, R0); }

  np new_node(const vc<X> &dat) {
    assert(L0 == 0 && R0 == len(dat));
    auto dfs = [&](auto &dfs, ll l, ll r) -> np {
      if (l == r) return nullptr;
      if (r == l + 1) return new_node(dat[l]);
      ll m = (l + r) / 2;
      np l_root = dfs(dfs, l, m), r_root = dfs(dfs, m, r);
      X x = MX::op(l_root->x, r_root->x);
      np root = new_node(x);
      root->l = l_root, root->r = r_root;
      return root;
    };
    return dfs(dfs, 0, len(dat));
  }

  X prod(np root, ll l, ll r) {
    assert(L0 <= l && l <= r && r <= R0);
    if (!root || l == r) return MX::id();
    X x = MX::id();
    prod_rec(root, L0, R0, l, r, x);
    return x;
  }

  np set(np root, ll i, const X &x) {
    assert(root && L0 <= i && i < R0);
    root = (root ? copy_node(root) : new_node());
    set_rec(root, L0, R0, i, x);
    return root;
  }

  np multiply(np root, ll i, const X &x) {
    assert(root && L0 <= i && i < R0);
    root = (root ? copy_node(root) : new_node());
    multiply_rec(root, L0, R0, i, x);
    return root;
  }

  template <typename F>
  ll max_right(np root, F check, ll L) {
    assert(root && L0 <= L && L <= R0 && check(MX::id()));
    X x = MX::id();
    return max_right_rec(root, check, L0, R0, L, x);
  }

  template <typename F>
  ll min_left(np root, F check, ll R) {
    assert(L0 <= R && R <= R0 && check(MX::id()));
    X x = MX::id();
    return min_left_rec(root, check, L0, R0, R, x);
  }

  // (idx, val)
  template <typename F>
  void enumerate(np root, F f) {
    if (!root) return;
    auto dfs = [&](auto &dfs, np c, ll l, ll r) -> void {
      if (!c) return;
      if (r - l == 1) {
        f(l, c->x);
        return;
      }
      ll m = (l + r) / 2;
      dfs(dfs, c->l, l, m);
      dfs(dfs, c->r, m, r);
    };
    dfs(dfs, root, L0, R0);
    return;
  }

  void reset() { pool.reset(); }

 private:
  np copy_node(np c) {
    if (!c || !PERSISTENT) return c;
    np n = pool.create();
    n->l = c->l, n->r = c->r, n->x = c->x;
    return n;
  }

  void set_rec(np c, ll l, ll r, ll i, const X &x) {
    assert(c);
    // もう c は新しくしてある
    if (r == l + 1) {
      c->x = x;
      return;
    }
    ll m = (l + r) / 2;
    if (l <= i && i < m) {
      c->l = (c->l ? copy_node(c->l) : new_node());
      set_rec(c->l, l, m, i, x);
    }
    if (m <= i && i < r) {
      c->r = (c->r ? copy_node(c->r) : new_node());
      set_rec(c->r, m, r, i, x);
    }
    X xl = (c->l ? c->l->x : default_prod(l, m));
    X xr = (c->r ? c->r->x : default_prod(m, r));
    c->x = MX::op(xl, xr);
    return;
  }

  void multiply_rec(np c, ll l, ll r, ll i, const X &x) {
    assert(c);
    // もう c は新しくしてある
    if (r == l + 1) {
      c->x = MX::op(c->x, x);
      return;
    }
    ll m = (l + r) / 2;
    if (l <= i && i < m) {
      c->l = (c->l ? copy_node(c->l) : new_node());
      multiply_rec(c->l, l, m, i, x);
    }
    if (m <= i && i < r) {
      c->r = (c->r ? copy_node(c->r) : new_node());
      multiply_rec(c->r, m, r, i, x);
    }
    X xl = (c->l ? c->l->x : default_prod(l, m));
    X xr = (c->r ? c->r->x : default_prod(m, r));
    c->x = MX::op(xl, xr);
    return;
  }

  void prod_rec(np c, ll l, ll r, ll ql, ll qr, X &x) {
    chmax(ql, l);
    chmin(qr, r);
    if (ql >= qr) return;
    if (!c) {
      x = MX::op(x, default_prod(ql, qr));
      return;
    }
    if (l == ql && r == qr) {
      x = MX::op(x, c->x);
      return;
    }
    ll m = (l + r) / 2;
    prod_rec(c->l, l, m, ql, qr, x);
    prod_rec(c->r, m, r, ql, qr, x);
  }

  // これ new node 作ってるのはさぼり
  template <typename F>
  ll max_right_rec(np c, const F &check, ll l, ll r, ll ql, X &x) {
    if (r <= ql) return R0;
    if (ql <= l && check(MX::op(x, c->x))) {
      x = MX::op(x, c->x);
      return R0;
    }
    if (r == l + 1) return l;
    ll m = (l + r) / 2;
    if (!c->l) c->l = new_node(l, m);
    ll k = max_right_rec(c->l, check, l, m, ql, x);
    if (k != R0) return k;
    if (!c->r) c->r = new_node(m, r);
    return max_right_rec(c->r, check, m, r, ql, x);
  }

  // これ new node 作ってるのはさぼり
  template <typename F>
  ll min_left_rec(np c, const F &check, ll l, ll r, ll qr, X &x) {
    if (qr <= l) return L0;
    if (r <= qr && check(MX::op(c->x, x))) {
      x = MX::op(x, c->x);
      return L0;
    }
    if (r == l + 1) return r;
    ll m = (l + r) / 2;
    if (!c->r) c->r = new_node(m, r);
    ll k = min_left_rec(c->r, check, m, r, qr, x);
    if (k != L0) return k;
    if (!c->l) c->l = new_node(l, m);
    return min_left_rec(c->l, check, l, m, qr, x);
  }
};
Back to top page