Problem p02345 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
#include <utility>

template <class Monoid, template <class> class Allocator = std::allocator,
          class Index = std::size_t>
class PersistentSegmentTree {
public:
  using value_type = Monoid;
  using reference = value_type &;
  using const_reference = const value_type &;
  using size_type = Index;

private:
  using F = std::function<value_type(const_reference)>;
  struct node_type {
    using pointer = std::shared_ptr<const node_type>;
    const value_type value;
    const pointer left, right;
    template <class L, class R>
    node_type(L &&l, R &&r)
        : value(l->value + r->value), left(std::forward<L>(l)),
          right(std::forward<R>(r)) {}
    node_type(const value_type &v) : value(v), left(), right() {}
    node_type(value_type &&v) : value(std::move(v)), left(), right() {}
    node_type(pointer &&p)
        : value(value_type()), left(p), right(std::move(p)) {}
    value_type range(size_type first, size_type last, size_type l,
                     size_type r) const {
      if (r <= first || last <= l)
        return value_type();
      if (first <= l && r <= last)
        return value;
      return left->range(first, last, l, (l + r) >> 1) +
             right->range(first, last, (l + r) >> 1, r);
    }
    pointer update(size_type index, size_type height, const F &f) const {
      if (!~height)
        return std::allocate_shared<const node_type>(alc, f(value));
      if (index >> height & 1)
        return std::allocate_shared<const node_type>(
            alc, left, right->update(index, height - 1, f));
      else
        return std::allocate_shared<const node_type>(
            alc, left->update(index, height - 1, f), right);
    }
  };

public:
  using allocator_type = Allocator<node_type>;
  using pointer = std::shared_ptr<const node_type>;

private:
  size_type height_;
  pointer root_;
  static allocator_type alc;
  static size_type getheight(size_type size) {
    return size ? getheight(size >> 1) + 1 : 0;
  }
  static pointer build(size_type height) {
    if (!height)
      return std::allocate_shared<const node_type>(alc, value_type());
    return std::allocate_shared<const node_type>(alc, build(height - 1));
  }
  explicit PersistentSegmentTree(pointer &&root, size_type height)
      : height_(height), root_(std::move(root)) {}

public:
  PersistentSegmentTree() : height_(0), root_() {}
  explicit PersistentSegmentTree(size_type size)
      : height_(size ? getheight(size - 1) : 0), root_(build(height_)) {}

  static void set_allocator(const allocator_type &x) { alc = x; }
  static void set_allocator(allocator_type &&x) { alc = std::move(x); }

  value_type range(size_type first, size_type last) const {
    return root_->range(first, last, 0, static_cast<size_type>(1) << height_);
  }

  PersistentSegmentTree update(size_type index, const F &f) const {
    return PersistentSegmentTree(root_->update(index, height_ - 1, f), height_);
  }
  PersistentSegmentTree update(size_type index, const value_type &data) const {
    return PersistentSegmentTree(
        root_->update(index, height_ - 1,
                      [&data](const_reference v) { return data; }),
        height_);
  }
};
template <class Monoid, template <class> class Allocator, class Index>
typename PersistentSegmentTree<Monoid, Allocator, Index>::allocator_type
    PersistentSegmentTree<Monoid, Allocator, Index>::alc = {};

#include <algorithm>
#include <iostream>

#include <algorithm>
#include <cstddef>
#include <limits>
#include <utility>

template <class T> struct Ass {
  using value_type = T;
  value_type a;
  bool f;
  Ass() : f(0) {}
  explicit Ass(const value_type &x) : a(x), f(1) {}
  explicit Ass(value_type &&x) : a(std::move(x)), f(1) {}
  Ass operator+(const Ass &o) const { return o.f ? o : *this; }
};

template <class T> struct Add {
  using value_type = T;
  value_type a;
  Add() : a(0) {}
  explicit Add(const value_type &x) : a(x) {}
  explicit Add(value_type &&x) : a(std::move(x)) {}
  Add operator+(const Add &o) const { return Add(a + o.a); }
};

template <class T> struct Mini {
  using value_type = T;
  value_type a;
  Mini() : a(std::numeric_limits<value_type>::max()) {}
  explicit Mini(const value_type &x) : a(x) {}
  explicit Mini(value_type &&x) : a(std::move(x)) {}
  Mini operator+(const Mini &o) const { return Mini(std::min(a, o.a)); }
  Mini operator*(const Ass<value_type> &o) const {
    return o.f ? Mini(o.a) : *this;
  }
  Mini operator*(const Add<value_type> &o) const { return Mini(a + o.a); }
};

template <class T> struct Maxi {
  using value_type = T;
  value_type a;
  Maxi() : a(std::numeric_limits<value_type>::lowest()) {}
  explicit Maxi(const value_type &x) : a(x) {}
  explicit Maxi(value_type &&x) : a(std::move(x)) {}
  Maxi operator+(const Maxi &o) const { return Maxi(std::max(a, o.a)); }
  Maxi operator*(const Ass<value_type> &o) const {
    return o.f ? Maxi(o.a) : *this;
  }
  Maxi operator*(const Add<value_type> &o) const { return Maxi(a + o.a); }
};

template <class T> struct Sum {
  using value_type = T;
  using size_type = std::size_t;
  value_type a;
  size_type s;
  Sum() : a(0), s(0) {}
  explicit Sum(const value_type &x, const size_type y) : a(x), s(y) {}
  explicit Sum(value_type &&x, const size_type y) : a(std::move(x)), s(y) {}
  Sum operator+(const Sum &o) const { return Sum(a + o.a, s + o.s); }
  Sum operator*(const Ass<value_type> &o) const {
    return o.f ? Sum(o.a * s, s) : *this;
  }
  Sum operator*(const Add<value_type> &o) const { return Sum(a + o.a * s, s); }
};

template <class T, class U> struct Multi {
  T operator()(const T &x, const U &y) const { return x * y; }
};

int main() {
  using M = Mini<int>;
  int n, q;
  std::cin >> n >> q;
  PersistentSegmentTree<M> T(n);
  while (q--) {
    int c, x, y;
    std::cin >> c >> x >> y;
    if (c)
      std::cout << T.range(x, y + 1).a << std::endl;
    else
      T = T.update(x, [y](const M &t) { return M(y); });
  }
  return 0;
}


Error: TLE

Fixed submission:

// #define NDEBUG
#define _CRT_SECURE_NO_WARNINGS
#include <array>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <limits>
#include <memory>
#include <string>
#include <type_traits>

template <class Integral> class Rirange;

template <class Integral = std::size_t> class irange {
public:
  using value_type = Integral;
  using reference = value_type &;
  using const_reference = const value_type &;
  class irangeitr {
    friend irange;
    value_type i;
    irangeitr(const value_type x) noexcept : i(x) {}

  public:
    void operator++() noexcept { ++i; }
    value_type &operator*() noexcept { return i; }
    const_reference operator*() const noexcept { return i; }
    bool operator!=(const irangeitr &x) const noexcept { return i < x.i; }
  };

private:
  const value_type f, l;

public:
  irange(const value_type first, const value_type last) noexcept
      : f(first), l(last) {}
  irangeitr begin() const noexcept { return irangeitr(f); }
  irangeitr end() const noexcept { return irangeitr(l); }
  Rirange<value_type> rev() const noexcept {
    return Rirange<value_type>(l - 1, f - 1);
  }
};
template <class Integral = std::size_t> class Rirange {
public:
  using value_type = Integral;
  using reference = value_type &;
  using const_reference = const value_type &;
  class Rirangeitr {
    friend Rirange;
    value_type i;
    Rirangeitr(const value_type x) noexcept : i(x) {}

  public:
    void operator++() noexcept { --i; }
    reference operator*() noexcept { return i; }
    const_reference operator*() const noexcept { return i; }
    bool operator!=(const Rirangeitr &x) const noexcept {
      return (!~x.i && ~i) || x.i < i;
    }
  };

private:
  const value_type f, l;

public:
  Rirange(const value_type x, const value_type y) noexcept : f(x), l(y) {}
  Rirangeitr begin() const noexcept { return Rirangeitr(f); }
  Rirangeitr end() const noexcept { return Rirangeitr(l); }
  irange<value_type> rev() const noexcept {
    return irange<value_type>(l + 1, f + 1);
  }
};

template <class T> bool maxi(T &a, const T &b) {
  if (b < a)
    return 0;
  a = b;
  return 1;
}
template <class T> bool mini(T &a, const T &b) {
  if (a < b)
    return 0;
  a = b;
  return 1;
}
template <class T> bool smaxi(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool smini(T &a, const T &b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}
struct customIO {
  int c;
  bool f;
  std::array<int, 30> buf;
  const std::array<int, 10> itoc;
  std::array<std::uint_least8_t, 256> ctoi_base;
  const std::uint_least8_t *const ctoi;
  void get_c() { c = fgetc(stdin); }
  void put_c(int x) { fputc(x, stdout); }
  bool vacant() { return c == ' ' || c == '\\n'; }
  operator int() { return 0; }

  explicit customIO()
      : itoc({'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}),
        ctoi(std::addressof(ctoi_base[-static_cast<std::int_fast16_t>(
            std::numeric_limits<char>::min())])) {
    for (std::uint_least8_t i = 0; i < 10; ++i)
      ctoi_base[static_cast<int>("0123456789"[i]) -
                static_cast<std::int_fast16_t>(
                    std::numeric_limits<char>::min())] = i;
  }
  // in

  void cueing() {
    while (get_c(), vacant())
      ;
  }
  template <class T>
  auto operator>>(T &d) ->
      typename std::enable_if<std::is_signed<T>::value, customIO &>::type {
    d = 0;
    f = 0;
    cueing();
    if (c == '-')
      f = 1, get_c();
    do
      d = d * 10 + ctoi[c];
    while (get_c(), !vacant());
    if (f)
      d = -d;
    return *this;
  }
  template <class T>
  auto operator>>(T &d) ->
      typename std::enable_if<!std::is_signed<T>::value, customIO &>::type {
    d = 0;
    cueing();
    do
      d = d * 10 + ctoi[c];
    while (get_c(), !vacant());
    return *this;
  }
  customIO &operator>>(char &d) {
    cueing();
    d = c;
    return *this;
  }
  customIO &operator>>(double &d) {
    scanf("%lf", &d);
    return *this;
  }
  customIO &operator>>(std::string &d) {
    d.clear();
    cueing();
    do
      d.push_back(c);
    while (get_c(), !vacant());
    return *this;
  }
  template <class T> T input() {
    T d;
    *this >> d;
    return d;
  }

  // out

  template <class T>
  auto operator<<(T d) ->
      typename std::enable_if<std::is_signed<T>::value, customIO &>::type {
    c = 0;
    f = 0;
    if (d < static_cast<T>(0))
      f = 1, d = -d;
    while (d)
      buf[c++] = itoc[d % 10], d /= 10;
    if (!c)
      buf[c++] = itoc[0];
    if (f)
      put_c('-');
    while (c--)
      put_c(buf[c]);
    return *this;
  }
  template <class T>
  auto operator<<(T d) ->
      typename std::enable_if<!std::is_signed<T>::value, customIO &>::type {
    c = 0;
    while (d)
      buf[c++] = itoc[d % 10], d /= 10;
    if (!c)
      buf[c++] = itoc[0];
    while (c--)
      put_c(buf[c]);
    return *this;
  }
  customIO &operator<<(char d) {
    put_c(d);
    return *this;
  }
  customIO &operator<<(double d) {
    printf("%f", d);
    return *this;
  }
  customIO &operator<<(const std::string &d) {
    for (const auto e : d)
      put_c(e);
    return *this;
  }
  customIO &operator<<(const char *d) {
    while (*d != '\\0')
      put_c(*(d++));
    return *this;
  }
  void endl() { put_c('\\n'); }
  void space() { put_c(' '); }
} IO;
#include <algorithm>
#include <array>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <memory>
#include <numeric>
#include <utility>
#include <vector>

template <class Integral, class T,
          std::size_t bitsize = std::numeric_limits<Integral>::digits()>
class WaveletMatrixSum {
public:
  using key_type = Integral;
  using linked_type = T;
  using value_type = std::pair<key_type, linked_type>;
  using size_type = std::size_t;

private:
  using uint32 = std::uint_least32_t;
  static size_type popcount32(uint32 c) {
#ifdef __GNUC__
    return __builtin_popcount(c);
#elif _MSC_VER_
    return _mm_popcnt_u32(c);
#else
    c = (c & 0x55555555) + ((c >> 1) & 0x55555555);
    c = (c & 0x33333333) + ((c >> 2) & 0x33333333);
    c = (c + (c >> 4)) & 0x0F0F0F0F;
    c += c >> 8;
    c += c >> 16;
    return static_cast<size_type>(c) & 0x3F;
#endif
  }
  struct FID {
    std::vector<uint32> dic;
    size_type cnt;
    key_type bit;
    std::vector<linked_type> sum;

    FID() {}

    void set(const size_type index) {
      dic[index >> 4 | 1] |= static_cast<uint32>(1) << (index & 0x1f);
    }
    void build() {
      const size_type len = dic.size();
      for (size_type j = 2; j < len; j += 2)
        dic[j] = dic[j - 2] + popcount32(dic[j - 1]);
    }

    size_type rank(const size_type last) const {
      return static_cast<size_type>(
                 dic[last >> 4 & ~static_cast<size_type>(1)]) +
             popcount32(dic[last >> 4 | 1] &
                        (static_cast<size_type>(1) << (last & 0x1f)) - 1);
    }
    bool access(const size_type index) const {
      return dic[index >> 4 | 1] >> (index & 0x1f) & 1;
    }
    linked_type range(const size_type first, const size_type last) const {
      return sum[last] - sum[first];
    }
  };
  std::array<FID, bitsize> matrix;
  value_type NOT_FOUND;
  size_type size_;

public:
  WaveletMatrixSum(const std::vector<value_type> &data,
                   const value_type NOT_FOUND = value_type())
      : size_(data.size()), NOT_FOUND(NOT_FOUND) {
    const size_type len = data.size(), block = ((len >> 5) + 1) << 1;
    std::vector<size_type> C(len), L(len), R(len);
    std::iota(C.begin(), C.end(), static_cast<size_type>(0));
    size_type l, r;
    key_type temp = static_cast<key_type>(1) << (bitsize - 1);
    for (auto &x : matrix) {
      x.dic.resize(block, 0);
      x.bit = temp;
      temp = temp >> 1 & ~temp;
      l = 0;
      r = 0;
      for (size_type i = 0; i < len; ++i)
        if (data[C[i]].first & x.bit)
          R[r++] = C[i], x.set(i);
        else
          L[l++] = C[i];
      x.cnt = l;
      x.build();
      std::swap(C, L);
      std::copy(R.begin(), R.begin() + r, C.begin() + l);
      for (size_type i = 0; i < len; ++i)
        x.sum.reserve(len + 1);
      x.sum.emplace_back();
      for (const auto e : C)
        x.sum.emplace_back(x.sum.back() + data[e].second);
    }
  }

  size_type size() const noexcept { return size_; }
  bool empty() const noexcept { return size() == 0; }

  value_type access(size_type index) const {
    assert(index < size());
    key_type ret = 0;
    for (const auto &x : matrix)
      if (x.access(index))
        ret |= x.bit, index = x.rank(index) + x.cnt;
      else
        index -= x.rank(index);
    return value_type(ret, matrix.back().range(index, index + 1));
  }
  value_type operator[](const size_type index) const {
    assert(index < size());
    return access(index);
  }
  size_type rank(size_type first, size_type last, const key_type data) const {
    assert(first <= size());
    assert(last <= size());
    assert(first <= last);
    for (const auto &x : matrix)
      if (data & x.bit)
        first = x.rank(first) + x.cnt, last = x.rank(last) + x.cnt;
      else
        first -= x.rank(first), last -= x.rank(last);
    return last - first;
  }
  linked_type rank_sum(size_type first, size_type last,
                       const key_type data) const {
    assert(first <= size());
    assert(last <= size());
    assert(first <= last);
    for (const auto &x : matrix)
      if (data & x.bit)
        first = x.rank(first) + x.cnt, last = x.rank(last) + x.cnt;
      else
        first -= x.rank(first), last -= x.rank(last);
    return matrix.back().range(first, last);
  }
  value_type quantile(size_type first, size_type last, size_type k) const {
    assert(first < size());
    assert(last <= size());
    assert(first < last);
    assert(last - first > k);
    key_type ret = 0;
    for (const auto &x : matrix) {
      const size_type l = x.rank(first), r = x.rank(last);
      if (r - l > k)
        first = l + x.cnt, last = r + x.cnt, ret |= x.bit;
      else
        first -= l, last -= r, k -= r - l;
    }
    return value_type(ret, matrix.back().range(last - k - 1, last - k));
  }
  value_type rquantile(size_type first, size_type last, size_type k) const {
    assert(first < size());
    assert(last <= size());
    assert(first < last);
    assert(last - first > k);
    return quantile(first, last, last - first - k - 1);
  }
  size_type less_than(size_type first, size_type last,
                      const key_type data) const {
    assert(first <= size());
    assert(last <= size());
    assert(first <= last);
    size_type ret = 0;
    for (const auto &x : matrix) {
      if (data & x.bit) {
        ret += last - first + x.rank(first) - x.rank(last);
        first = x.rank(first) + x.cnt;
        last = x.rank(last) + x.cnt;
      } else {
        first -= x.rank(first);
        last -= x.rank(last);
      }
    }
    return ret;
  }
  linked_type less_than_sum(size_type first, size_type last,
                            const key_type data) const {
    assert(first <= size());
    assert(last <= size());
    assert(first <= last);
    linked_type ret = linked_type();
    for (const auto &x : matrix) {
      if (data & x.bit) {
        ret = ret + x.range(first - x.rank(first), last - x.rank(last));
        first = x.rank(first) + x.cnt;
        last = x.rank(last) + x.cnt;
      } else {
        first -= x.rank(first);
        last -= x.rank(last);
      }
    }
    return ret;
  }
  size_type at_least(size_type first, size_type last,
                     const key_type data) const {
    assert(first <= size());
    assert(last <= size());
    assert(first <= last);
    size_type ret = 0;
    for (const auto &x : matrix) {
      if (data & x.bit) {
        first = x.rank(first) + x.cnt;
        last = x.rank(last) + x.cnt;
      } else {
        ret += x.rank(last) - x.rank(first);
        first -= x.rank(first);
        last -= x.rank(last);
      }
    }
    return last - first + ret;
  }
  linked_type at_least_sum(size_type first, size_type last,
                           const key_type data) const {
    assert(first <= size());
    assert(last <= size());
    assert(first <= last);
    linked_type ret = linked_type();
    for (const auto &x : matrix) {
      if (data & x.bit) {
        first = x.rank(first) + x.cnt;
        last = x.rank(last) + x.cnt;
      } else {
        ret = ret + x.range(x.rank(first) + x.cnt, x.rank(last) + x.cnt);
        first -= x.rank(first);
        last -= x.rank(last);
      }
    }
    return ret + matrix.back().range(first, last);
  }
  size_type greater_than(size_type first, size_type last,
                         const key_type data) const {
    assert(first <= size());
    assert(last <= size());
    assert(first <= last);
    size_type ret = 0;
    for (const auto &x : matrix) {
      if (data & x.bit) {
        first = x.rank(first) + x.cnt;
        last = x.rank(last) + x.cnt;
      } else {
        ret += x.rank(last) - x.rank(first);
        first -= x.rank(first);
        last -= x.rank(last);
      }
    }
    return ret;
  }
  linked_type greater_than_sum(size_type first, size_type last,
                               const key_type data) const {
    assert(first <= size());
    assert(last <= size());
    assert(first <= last);
    linked_type ret = linked_type();
    for (const auto &x : matrix) {
      if (data & x.bit) {
        first = x.rank(first) + x.cnt;
        last = x.rank(last) + x.cnt;
      } else {
        ret = ret + x.range(x.rank(first) + x.cnt, x.rank(last) + x.cnt);
        first -= x.rank(first);
        last -= x.rank(last);
      }
    }
    return ret;
  }
  size_type at_most(size_type first, size_type last,
                    const key_type data) const {
    assert(first <= size());
    assert(last <= size());
    assert(first <= last);
    size_type ret = 0;
    for (const auto &x : matrix) {
      if (data & x.bit) {
        ret += last - first + x.rank(first) - x.rank(last);
        first = x.rank(first) + x.cnt;
        last = x.rank(last) + x.cnt;
      } else {
        first -= x.rank(first);
        last -= x.rank(last);
      }
    }
    return last - first + ret;
  }
  linked_type at_most_sum(size_type first, size_type last,
                          const key_type data) const {
    assert(first <= size());
    assert(last <= size());
    assert(first <= last);
    linked_type ret = linked_type();
    for (const auto &x : matrix) {
      if (data & x.bit) {
        ret = ret + x.range(first - x.rank(first), last - x.rank(last));
        first = x.rank(first) + x.cnt;
        last = x.rank(last) + x.cnt;
      } else {
        first -= x.rank(first);
        last -= x.rank(last);
      }
    }
    return ret + matrix.back().range(first, last);
  }
  size_type rangefreq(size_type first, size_type last, const key_type lower,
                      const key_type upper) const {
    assert(first <= size());
    assert(last <= size());
    assert(first <= last);
    assert(lower <= upper);
    return less_than(first, last, upper) - less_than(first, last, lower);
  }
  linked_type rangefreq_sum(size_type first, size_type last,
                            const key_type lower, const key_type upper) const {
    assert(first <= size());
    assert(last <= size());
    assert(first <= last);
    assert(lower <= upper);
    return less_than_sum(first, last, upper) -
           less_than_sum(first, last, lower);
  }
  linked_type maxk_sum(size_type first, size_type last, size_type k) const {
    assert(first <= size());
    assert(last <= size());
    assert(first <= last);
    assert(last - first >= k);
    linked_type ret = linked_type();
    for (const auto &x : matrix) {
      const size_type l = x.rank(first), r = x.rank(last);
      if (r - l > k) {
        first = l + x.cnt;
        last = r + x.cnt;
      } else {
        ret = ret + x.range(l + x.cnt, r + x.cnt);
        first -= l;
        last -= r;
        k -= r - l;
      }
    }
    return ret + matrix.back().range(last - k, last);
  }
  linked_type mink_sum(size_type first, size_type last, size_type k) const {
    assert(first <= size());
    assert(last <= size());
    assert(first <= last);
    assert(last - first >= k);
    linked_type ret = linked_type();
    for (const auto &x : matrix) {
      const size_type l = first - x.rank(first), r = last - x.rank(last);
      if (r - l > k) {
        first = l;
        last = r;
      } else {
        ret = ret + x.range(l, r);
        first += x.cnt - l;
        last += x.cnt - r;
        k -= r - l;
      }
    }
    return ret + matrix.back().range(first, first + k);
  }
  value_type successor(const size_type first, const size_type last,
                       const key_type data) const {
    assert(first <= size());
    assert(last <= size());
    assert(first <= last);
    const size_type k = less_than(first, last, data);
    return last - first == k ? NOT_FOUND : rquantile(first, last, k);
  }
  value_type predecessor(const size_type first, const size_type last,
                         const key_type data) const {
    assert(first <= size());
    assert(last <= size());
    assert(first <= last);
    const size_type k = greater_than(first, last, data);
    return last - first == k ? NOT_FOUND : quantile(first, last, k);
  }
  value_type strict_succ(const size_type first, const size_type last,
                         const key_type data) const {
    assert(first <= size());
    assert(last <= size());
    assert(first <= last);
    const size_type k = greater_than(first, last, data);
    return k ? quantile(first, last, k - 1) : NOT_FOUND;
  }
  value_type strict_pred(const size_type first, const size_type last,
                         const key_type data) const {
    assert(first <= size());
    assert(last <= size());
    assert(first <= last);
    const size_type k = less_than(first, last, data);
    return k ? rquantile(first, last, k - 1) : NOT_FOUND;
  }
};
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 intl32 = std::int_least32_t;
using intl64 = std::int_least64_t;
using uintl32 = std::uint_least32_t;
using uintl64 = std::uint_least64_t;

#include <utility>
#include <vector>

int main() {
  /*
  const auto n = IO.input<uint32>();
  std::vector<std::pair<uint32,int64>> a(n * 3);
  for (auto &e : a) {
          IO >> e.first;
          e.second = e.first;
  }
  WaveletMatrixSum<uint32, int64, 30> W(a);
  int64 ans = INT64_MIN;
  for (const auto i : irange<>(n, n * 2 + 1))
          smaxi(ans, W.maxk_sum(0, i, n) - W.mink_sum(i, n * 3, n));
  IO << ans << '\\n';
  */
  uint32 n, q;
  IO >> n >> q;
  std::vector<std::pair<uintl32, uintl32>> a(n);
  for (auto &e : a)
    e.first = e.second = 2147483647;
  while (q--) {
    uint32 c, x, y;
    IO >> c >> x >> y;
    if (c) {
      WaveletMatrixSum<uintl32, uintl32, 31> W(a);
      IO << W.mink_sum(x, y + 1, 1) << '\\n';
    } else {
      a[x].first = a[x].second = y;
    }
  }
  return 0;
}