Problem:
RMQ and RAQ

Write a program which manipulates a sequence $A$ = {$a_0, a_1, ..., a_{n-1}$} with the following operations:

$add(s, t, x)$ : add $x$ to $a_s, a_{s+1}, ..., a_t$.

$find(s, t)$ : report the minimum value in $a_s, a_{s+1}, ..., a_t$.

Note that the initial values of $a_i ( i = 0, 1, ..., n-1 )$ are 0.

Input

$n$ $q$
$query_1$
$query_2$
:
$query_q$

In the first line, $n$ (the number of elements in $A$) and $q$ (the number of queries) are given. Then, $i$th query $query_i$ is given in the following format:

0 $s$ $t$ $x$

or

1 $s$ $t$

The first digit represents the type of the query. '0' denotes $add(s, t, x)$ and '1' denotes $find(s, t)$.

Output

For each $find$ query, print the minimum value.

Constraints

$1 ≤ n ≤ 100000$

$1 ≤ q ≤ 100000$

$0 ≤ s ≤ t < n$

$-1000 ≤ x ≤ 1000$

Sample Input 1

6 7
0 1 3 1
0 2 4 -2
1 0 5
1 0 1
0 3 5 3
1 3 4
1 0 5

Sample Output 1

-2
0
1
-1

Solution in C++14 (judge verdict: Accepted)

#include <cstdio>
#include <cstdint>
#include <climits>
#include <vector>
#include <algorithm>
#include <utility>

template <
  typename Monoid,
  typename Container = std::vector<typename Monoid::first_type>,
  typename SubContainer = std::vector<typename Monoid::second_type>
>
class segment_tree {
public:
  using first_type = typename Monoid::first_type;
  using second_type = typename Monoid::second_type;
  using value_type = first_type;
  using binary_operation = typename Monoid::binary_operation;
  using external_binary_operation = typename Monoid::external_binary_operation;
  using merge_operation = typename Monoid::merge_operation;
  using container = Container;
  using sub_container = SubContainer;

private:
  size_t M_base_size;
  binary_operation M_op1;
  external_binary_operation M_op2;
  merge_operation M_op3;
  container M_c;
  sub_container M_d;  // deferred

  void M_build0(size_t p) {
    M_c[p] = M_op2(M_op1(M_c[p<<1|0], M_c[p<<1|1]), M_d[p]);
  }

  void M_build(size_t i) {
    while (i > 1) {
      i >>= 1;
      M_build0(i);
    }
  }

  void M_resolve(size_t i) {
    size_t h = (sizeof(size_t) * CHAR_BIT) - __builtin_clzll(M_base_size*2);
    for (size_t s = h; s > 0; --s) {
      size_t p = i >> s;
      if (M_d[p] != M_op3.identity) {
        M_apply(p<<1|0, M_d[p]);
        M_apply(p<<1|1, M_d[p]);
        M_d[p] = M_op3.identity;
      }
    }
  }

  void M_apply(size_t i, second_type const& x) {
    M_c[i] = M_op2(M_c[i], x);
    if (i < M_base_size) M_d[i] = M_op3(M_d[i], x);
  }

public:
  segment_tree() = default;
  segment_tree(segment_tree const&) = default;
  segment_tree(segment_tree&&) = default;

  segment_tree(size_t n, first_type const& x = binary_operation().identity):
    M_base_size(n),
    M_op1(binary_operation()),
    M_op2(external_binary_operation()),
    M_op3(merge_operation()),
    M_c(n+n, x), M_d(n, M_op3.identity)
  {
    for (size_t i = n; i--;)
      M_c[i] = M_op1(M_c[i<<1], M_c[i<<1|1]);
  }

  template <typename InputIt>
  segment_tree(InputIt first, InputIt last):
    M_base_size(std::distance(first, last)),
    M_op1(binary_operation()),
    M_op2(external_binary_operation()),
    M_op3(merge_operation()),
    M_c(M_base_size*2), M_d(M_base_size, M_op3.identity)
  {
    for (size_t i = M_base_size; first != last; ++i)
      M_c[i] = *first++;
    for (size_t i = M_base_size; i--;)
      M_c[i] = M_op1(M_c[i<<1|0], M_c[i<<1|1]);
  }

  segment_tree& operator =(segment_tree const&) = default;
  segment_tree& operator =(segment_tree&&) = default;

  void modify(size_t l, size_t r, second_type const& x) {
    l += M_base_size;
    r += M_base_size;
    size_t l0 = l;
    size_t r0 = r;
    while (l < r) {
      if (l & 1) M_apply(l++, x);
      if (r & 1) M_apply(--r, x);
      l >>= 1;
      r >>= 1;
    }
    M_build(l0);
    M_build(r0-1);
  }

  first_type accumulate(size_t l, size_t r) {
    first_type resl = M_op1.identity;
    first_type resr = resl;
    l += M_base_size;
    r += M_base_size;
    M_resolve(l);
    M_resolve(r-1);
    while (l < r) {
      if (l & 1) resl = M_op1(resl, M_c[l++]);
      if (r & 1) resr = M_op1(M_c[--r], resr);
      l >>= 1;
      r >>= 1;
    }
    return M_op1(resl, resr);
  }

  first_type operator [](size_t i) {
    i += M_base_size;
    M_resolve(i);
    i >>= __builtin_ctzll(i);
    return M_c[i];
  }
};

template <typename Tp>
struct range_min_range_add {
  using first_type = Tp;
  using second_type = Tp;
  struct binary_operation {
    first_type identity = std::numeric_limits<Tp>::max();
    first_type operator ()(first_type const& x, first_type const& y) const {
      return std::min(x, y);
    }
  };
  struct external_binary_operation {
    first_type operator ()(first_type const& x, second_type const& y) const {
      return x + y;
    }
  };
  struct merge_operation {
    second_type identity{0};
    second_type operator ()(second_type const& x, second_type const& y) const {
      return x + y;
    }
  };
};

int main() {
  size_t n, q;
  scanf("%zu %zu", &n, &q);
  segment_tree<range_min_range_add<intmax_t>> st(n, 0);

  for (size_t i = 0; i < q; ++i) {
    int t;
    scanf("%d", &t);

    if (t == 0) {
      // add(s, t, x)
      size_t s, t;
      intmax_t x;
      scanf("%zu %zu %jd", &s, &t, &x);
      st.modify(s, t+1, x);
    } else if (t == 1) {
      // getSum(s, t)
      size_t s, t;
      scanf("%zu %zu", &s, &t);
      printf("%jd\n", st.accumulate(s, t+1));
    }
  }
}