Problem p02350 (C++) — buggy submission, verdict: Memory Limit Exceeded

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

struct Data {
  using type = int;
  type val, lazy;

  static type id() { return INT_MAX; }
  static type op(const type &l, const type &r) { return min(l, r); }

  Data(type v) : val(v), lazy(-1) {}
  void update(type a) { lazy = a; }
  type get() { return lazy == -1 ? val : lazy; }
  void push() {
    if (lazy == -1)
      return;
    val = lazy;
  }
  void push(Data &l, Data &r) {
    if (lazy == -1)
      return;
    val = lazy;
    l.lazy = lazy;
    r.lazy = lazy;
  }
};

template <typename M> class LazySegmentTree {
  using T = typename M::type;
  const int n;
  vector<M> data;
  int size(int n) {
    int res = 1;
    while (res < n)
      res <<= 1;
    return res;
  }
  void suc(int l, int r, int node, int lb, int ub, T val) {
    if (ub <= l || r <= lb)
      return;
    if (ub - lb > 1)
      data[node].push(data[node * 2], data[node * 2 + 1]);
    if (l <= lb && ub <= r) {
      data[node].update(val);
      return;
    }
    int c = (lb + ub) / 2;
    suc(l, r, node * 2, lb, c, val);
    suc(l, r, node * 2 + 1, c, ub, val);
    data[node] = M::op(data[node * 2].get(), data[node * 2 + 1].get());
  }
  T sub(int l, int r, int node, int lb, int ub) {
    if (ub <= l || r <= lb)
      return M::id();
    if (l <= lb && ub <= r)
      return data[node].get();
    data[node].push(data[node * 2], data[node * 2 + 1]);
    int c = (lb + ub) / 2;
    return M::op(sub(l, r, node * 2, lb, c), sub(l, r, node * 2 + 1, c, ub));
  }

public:
  LazySegmentTree(int n_) : n(size(n_)), data(n * 2, M::id()) {}
  void init(const vector<T> &data_) {
    for (int i = 0; i < (int)data_.size(); i++)
      data[i + n] = data_[i];
    for (int i = n - 1; i >= 0; i--)
      data[i] = M::op(data[i * 2], data[i * 2 + 1]);
  }
  void update(int l, int r, T val) { suc(l, r + 1, 1, 0, n, val); }
  T find(int l, int r) { return sub(l, r + 1, 1, 0, n); }
};

int main() {
  ios::sync_with_stdio(false), cin.tie(0);
  int n, q, com, x, y, val;
  cin >> n >> q;
  LazySegmentTree<Data> st(n);
  while (q--) {
    cin >> com >> x >> y;
    if (com) {
      printf("%d\\n", st.find(x, y));
    } else {
      cin >> val;
      st.update(x, y, val);
    }
  }
  return 0;
}

Error: MLE

Fixed submission:

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

using ll = long long;

struct RMQ {
  using type = int;
  static type id1() { return INT_MAX; }
  static type id2() { return -1; }
  static type op1(const type &l, const type &r) { return min(l, r); }
  static type op2(const type &l, const type &r) { return r != -1 ? r : l; }
};

const function<int(int, int)> minQ = [](int l, int r) { return min(l, r); };

template <typename T> class node {
public:
  T val, lazy;
  node<T> *l, *r;
  node() {}
  void init(T val_, T lazy_, node<T> *l_ = nullptr, node<T> *r_ = nullptr) {
    val = val_;
    lazy = lazy_;
    l = l_;
    r = r_;
  }
};

template <typename M> class SaikyoSegmentTree {
  using T = typename M::type;
  const ll n;
  vector<node<T> *> root;
  vector<node<T>> pool;
  int it;
  ll size(ll n) {
    ll res = 1;
    while (res < n)
      res <<= 1;
    return res;
  }
  node<T> *new_node() {
    pool[it].init(M::id1(), M::id2());
    return &pool[it++];
  }
  node<T> *fix(node<T> *t) {
    pool[it] = *t;
    return &pool[it++];
  }
  node<T> *push(node<T> *t, ll lb, ll ub) {
    t = fix(t);
    if (lb + 1 < ub) {
      if (t->l == nullptr)
        t->l = new_node();
      else
        t->l = fix(t->l);
      if (t->r == nullptr)
        t->r = new_node();
      else
        t->r = fix(t->r);
      t->l->lazy = M::op2(t->l->lazy, t->lazy);
      t->r->lazy = M::op2(t->r->lazy, t->lazy);
    }
    t->val = M::op2(t->val, t->lazy);
    t->lazy = M::id2();
    return t;
  }
  node<T> *suc(ll l, ll r, node<T> *t, ll lb, ll ub, T val) {
    if (ub <= l || r <= lb)
      return t;
    if (t == nullptr)
      t = new_node();
    if (l <= lb && ub <= r) {
      t->lazy = M::op2(t->lazy, val);
      return t;
    }
    t = push(t, lb, ub);
    int c = (lb + ub) / 2;
    t->l = suc(l, r, t->l, lb, c, val);
    t->r = suc(l, r, t->r, c, ub, val);
    t->val = M::op1(t->l == nullptr ? M::id1() : M::op2(t->l->val, t->l->lazy),
                    t->r == nullptr ? M::id1() : M::op2(t->r->val, t->r->lazy));
    return t;
  }
  node<T> *sub(ll l, ll r, node<T> *t, ll lb, ll ub, T &res) {
    if (t == nullptr || ub <= l || r <= lb)
      return t;
    t = push(t, lb, ub);
    if (l <= lb && ub <= r) {
      res = M::op1(res, t->val);
      return t;
    }
    int c = (lb + ub) / 2;
    t->l = sub(l, r, t->l, lb, c, res);
    t->r = sub(l, r, t->r, c, ub, res);
    return t;
  }

public:
  SaikyoSegmentTree(ll n_, int PMAX = 2e7)
      : n(size(n_)), root(1, nullptr), pool(PMAX), it(0) {}
  void update(ll l, ll r, T val, int rt = -1) {
    if (rt == -1)
      rt = root.size() - 1;
    assert(0 <= rt && rt < (int)root.size());
    root.push_back(suc(l, r + 1, root[rt], 0, n, val));
  }
  T find(ll l, ll r, int rt = -1) {
    if (rt == -1)
      rt = root.size() - 1;
    assert(0 <= rt && rt < (int)root.size());
    T res = M::id1();
    root.push_back(sub(l, r + 1, root[rt], 0, n, res));
    return res;
  }
  int getversion() { return root.size() - 1; }
};

int main() {
  ios::sync_with_stdio(false), cin.tie(0);
  int n, q, com, x, y, val;
  cin >> n >> q;
  SaikyoSegmentTree<RMQ> st(n);
  while (q--) {
    cin >> com >> x >> y;
    if (com) {
      printf("%d\\n", st.find(x, y));
    } else {
      cin >> val;
      st.update(x, y, val);
    }
  }
  return 0;
}