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

#include <cassert>
#include <cstdint>
#include <functional>
#include <vector>

template <typename Abelian> class FenwickTree {
  using uint32 = std::uint_fast32_t;
  using const_reference = const Abelian &;
  using F = std::function<Abelian(const_reference, const_reference)>;
  const Abelian neutral_;
  const F p, m;
  std::vector<Abelian> tree;

public:
  FenwickTree(const uint32 size, const_reference neutral = Abelian(),
              const F &p = std::plus<Abelian>(),
              const F &m = std::minus<Abelian>())
      : neutral_(neutral), p(p), m(m), tree(size + 1, neutral_) {}
  FenwickTree(const uint32 size, const_reference neutral, const F &p,
              const std::function<Abelian(const_reference)> &n)
      : neutral_(neutral), p(p),
        m([&p, &n](const_reference l, const_reference r) {
          return p(l, n(r));
        }),
        tree(size + 1, neutral_) {}
  void update(uint32 index, const std::function<void(Abelian)> &g) {
    assert(index < tree.size() - 1);
    ++index;
    const Abelian a = tree[index];
    g(tree[index]);
    const_reference b = tree[index];
    while ((index += index & ~index + 1) < tree.size())
      tree[index] = p(m(tree[index], a), b);
  }
  void update(uint32 index, const_reference data) {
    update(index, [&data](Abelian &d) { d = data; });
  }
  void add(uint32 index, const_reference diff) {
    assert(index < tree.size() - 1);
    ++index;
    do
      tree[index] = p(tree[index], diff);
    while ((index += index & ~index + 1) < tree.size());
  }
  Abelian range(uint32 end) const {
    assert(end < tree.size());
    Abelian ret = neutral_;
    do
      ret = p(tree[end], ret);
    while (end &= end - 1);
    return ret;
  }
  Abelian range(uint32 begin, uint32 end) const {
    assert(begin <= end);
    return m(range(end), range(begin));
  }
  Abelian operator[](uint32 index) const {
    assert(index < tree.size() - 1);
    return range(index, index + 1);
  }
};

#include <iostream>
int main(void) {
  int n, q;
  std::cin >> n >> q;
  FenwickTree<int> T(n, 0);
  while (q--) {
    int c, x, y;
    std::cin >> c >> x >> y;
    if (c) {
      std::cout << T.range(x - 1, y) << "\\n";
    } else {
      T.add(x - 1, y);
    }
  }
  return 0;
}


Error: MLE

Fixed submission:

#include <algorithm>
#include <array>
#include <climits>
#include <cstdint>
#include <functional>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stack>
#include <stdlib.h>
#include <string>
#include <time.h>
#include <utility>
#include <vector>

using int32 = std::int_fast32_t;
using int64 = std::int_fast64_t;
using uint32 = std::uint_fast32_t;
using uint64 = std::uint_fast64_t;
using uintl32 = std::uint_least32_t;
using intl32 = std::int_least32_t;

template <typename Monoid> class avl_tree {
  static constexpr uint64 allocsize = (uint64)1 << 14;
  struct node_t {
    node_t *left, *right;
    Monoid value, sum;
    uintl32 size, height, ref;
    // node_t(){}
    // node_t(node_t *l, node_t *r, Monoid va, Monoid su, uintl32 s, uintl32 h,
    // uintl32 re) : 	left(l), right(r), value(va), sum(su), size(s), height(h),
    //ref(re) {}
    void gc(void) {
      left->reset();
      right->reset();
      left = garbage;
      garbage = this;
    }
    void reset(void) {
      if (!(--ref))
        gc();
    }
  };
  static node_t *garbage;
  static node_t *data_;
  static node_t *nil;
  node_t *root_;
  avl_tree(node_t *root) : root_(root) { ++root->ref; }
  static node_t *alloc(void) {
    if (!garbage) {
      garbage = (node_t *)malloc(allocsize * (uint64)sizeof(node_t));
      uint32 i = allocsize;
      (garbage + i - 1)->left = nullptr;
      while (--i) {
        (garbage + i - 1)->left = (garbage + i);
      }
    }
    node_t *ret = garbage;
    garbage = garbage->left;
    return ret;
  }
  static node_t *make(node_t *l, node_t *r, Monoid &m) {
    node_t *ret = alloc();
    ret->left = l;
    ret->right = r;
    ret->value = m;
    ret->sum = (l->sum + m) + r->sum;
    ret->size = l->size + r->size + 1;
    ret->height = std::max(l->height, r->height) + 1;
    ret->ref = 0;
    ++l->ref;
    ++r->ref;
    return ret;
  }
  static node_t *adjustR(node_t *n) {
    if (n->right->height - n->left->height != 2)
      return n;
    if (n->right->right->height + 2 == n->right->height) {
      node_t *t = n->right->left;
      t = make(make(n->left, t->left, n->value),
               make(t->right, n->right->right, n->right->value), t->value);
      n->gc();
      return t;
    } else {
      node_t *t = n->right;
      t = make(make(n->left, t->left, n->value), t->right, t->value);
      n->gc();
      return t;
    }
  }
  static node_t *adjustL(node_t *n) {
    if (n->left->height - n->right->height != 2)
      return n;
    if (n->left->left->height + 2 == n->left->height) {
      node_t *t = n->left->right;
      t = make(make(n->left->left, t->left, n->left->value),
               make(t->right, n->right, n->value), t->value);
      n->gc();
      return t;
    } else {
      node_t *t = n->left;
      t = make(t->left, make(t->right, n->right, n->value), t->value);
      n->gc();
      return t;
    }
  }
  static node_t *insert_(node_t *n, uint32 position) {
    if (n == nil)
      return data_;
    if (n->left->size < position) {
      return adjustR(make(
          n->left, insert_(n->right, position - n->left->size - 1), n->value));
    } else {
      return adjustL(make(insert_(n->left, position), n->right, n->value));
    }
  }
  static node_t *erase_(node_t *n, uint32 position) {
    if (n->left->size > position) {
      return adjustR(make(erase_(n->left, position), n->right, n->value));
    } else if (n->left->size < position) {
      return adjustL(make(
          n->left, erase_(n->right, position - n->left->size - 1), n->value));
    }
    if (n->left == nil) {
      data_ = n;
      if (n->right == nil) {
        return nil;
      } else {
        return make(nil, nil, n->right->value);
      }
    } else {
      if (n->right == nil) {
        return make(nil, nil, n->left->value);
      } else {
        node_t *t = erase_(n->right, 0);
        return adjustL(make(n->left, t, data_->value));
      }
    }
  }
  static std::pair<node_t *, node_t *> split_(node_t *n, uint32 position) {
    if (n == nil)
      return {nil, nil};
    if (n->left->size < position) {
      std::pair<node_t *, node_t *> temp =
          split_(n->right, position - n->left->size - 1);
      return {merge_(n->left, temp.first, n), temp.second};
    } else {
      std::pair<node_t *, node_t *> temp = split_(n->left, position);
      return {temp.first, merge_(temp.second, n->right, n)};
    }
  }
  static node_t *merge_(node_t *l, node_t *r, node_t *n) {
    if (l->height > r->height) {
      data_ = make(nil, r, n->value);
      return merge_subR(l);
    } else {
      data_ = make(l, nil, n->value);
      return merge_subL(r);
    }
  }
  static node_t *merge_subL(node_t *n) {
    if (n->height >= data_->height) {
      return adjustL(make(merge_subL(n->left), n->right, n->value));
    }
    node_t *ret = make(data_->left, n, data_->value);
    data_->gc();
    return ret;
  }
  static node_t *merge_subR(node_t *n) {
    if (n->height >= data_->height) {
      return adjustR(make(n->left, merge_subR(n->right), n->value));
    }
    node_t *ret = make(n, data_->right, data_->value);
    data_->gc();
    return ret;
  }
  static Monoid more_than(node_t *n, uint32 position) {
    Monoid ret;
    while (n != nil) {
      if (n->left->size < position) {
        position -= n->left->size + 1;
        n = n->right;
      } else {
        ret = (n->value + n->right->sum) + ret;
        n = n->left;
      }
    }
    return ret;
  }
  static Monoid less_than(node_t *n, uint32 position) {
    Monoid ret;
    while (n != nil) {
      if (n->left->size < position) {
        position -= n->left->size + 1;
        ret = ret + (n->left->sum + n->value);
        n = n->right;
      } else {
        n = n->left;
      }
    }
    return ret;
  }
  node_t *leftest() {
    node_t *n = root_;
    while (n->left != nil) {
      n = n->left;
    }
    return n;
  }
  static void show_(node_t *n) {
    std::cout << "(";
    if (n->left != nil) {
      show_(n->left);
      std::cout << "←";
    }
    std::cout << n->value.e << " " << n->height;
    if (n->right != nil) {
      std::cout << "→";
      show_(n->right);
    }
    std::cout << ")";
  }

public:
  avl_tree() : root_(nil) { ++nil->ref; }
  avl_tree(const avl_tree &other) : root_(other.root_) { ++root_->ref; }
  avl_tree &operator=(const avl_tree &other) {
    root_->reset();
    root_ = other.root_;
    ++root_->ref;
    return *this;
  }
  ~avl_tree() { root_->reset(); }
  Monoid access(uint32 index) {
    node_t *n = root_;
    while (index != n->left->size) {
      if (n->left->size < index) {
        index -= n->left->size + 1;
        n = n->right;
      } else {
        n = n->left;
      }
    }
    return n->value;
  }
  static avl_tree merge(const avl_tree &L, const avl_tree &R) {
    avl_tree<Monoid> n = merge_(L.root_, R.root_, alloc());
    return n.erase(L.size());
  }
  std::pair<avl_tree, avl_tree> split(uint32 position) {
    std::pair<node_t *, node_t *> n = split_(root_, position);
    return {avl_tree(n.first), avl_tree(n.second)};
  }
  avl_tree insert(uint32 position, Monoid data) {
    data_ = make(nil, nil, data);
    node_t *n = insert_(root_, position);
    return avl_tree(n);
  }
  avl_tree erase(uint32 position) { return avl_tree(erase_(root_, position)); }
  static avl_tree singlton(Monoid data) {
    return avl_tree(make(nil, nil, data));
  }
  Monoid fold() { return root_->sum; }
  Monoid range(uint32 begin, uint32 end) {
    if (begin >= end)
      return Monoid();
    node_t *n = root_;
    while (1) {
      if (n->left->size >= begin) {
        if (n->left->size < end)
          return (more_than(n->left, begin) + n->value) +
                 less_than(n->right, end - n->left->size - 1);
        n = n->left;
      } else {
        begin -= n->left->size + 1;
        end -= n->left->size + 1;
        n = n->right;
      }
    }
  }
  uint32 size(void) const { return root_->size; }
  void show() {
    show_(root_);
    std::cout << "\\n";
  }
  static void set(void) { *nil = {nil, nil, Monoid(), Monoid(), 0, 0, 100}; }
};
template <typename Monoid>
typename avl_tree<Monoid>::node_t *avl_tree<Monoid>::garbage = nullptr;
template <typename Monoid>
typename avl_tree<Monoid>::node_t *avl_tree<Monoid>::data_ = nullptr;
template <typename Monoid>
typename avl_tree<Monoid>::node_t *avl_tree<Monoid>::nil =
    (node_t *)malloc(sizeof(avl_tree<Monoid>::node_t));
// template<typename Monoid>
// typename avl_tree<Monoid>::node_t *avl_tree<Monoid>::*nil = {
// nil,nil,Monoid(),Monoid(),0,0,100 };

struct ADD {
  int64 e;
  ADD(int64 t = 0) { e = t; }
  ADD operator*(const ADD &other) { return ADD(e + other.e); }
};

struct SUM {
  int64 e;
  int64 s;
  SUM(int64 x = 0, int64 y = 1) {
    e = x;
    s = y;
  }
  void set() {
    e = 0;
    s = 1;
  }
  void reverse(void) {}
  SUM operator+(const SUM &other) { return SUM(e + other.e, s + other.s); };
  SUM operator*(const ADD &other) { return SUM(e + (s * other.e), s); }
};

int main(void) {
  std::ios::sync_with_stdio(false);
  std::cin.tie(0);
  avl_tree<SUM> T;
  uint32 n, q;
  std::cin >> n >> q;
  avl_tree<SUM>::set();
  for (uint32 i = 0; i < n; ++i) {
    T = T.insert(0, SUM());
  }
  uint32 c, x, y;
  while (q--) {
    std::cin >> c >> x >> y;
    // T.show();
    if (c) {
      auto U = T.split(x - 1);
      auto V = U.second.split(y - x + 1);
      std::cout << V.first.fold().e << "\\n";
    } else {
      auto U = T.split(x - 1);
      // U.first.show();
      // U.second.show();
      auto V = U.second.split(1);
      // V.second.show();
      auto W = avl_tree<SUM>::singlton(V.first.fold() + SUM(y));
      T = avl_tree<SUM>::merge(avl_tree<SUM>::merge(U.first, W), V.second);
    }
    // T.show();
  }
  return 0;
}