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

// use 2^i size by yourself
/// --- LazySegmentTree Library {{{ ///

/*
   struct Monoid {
   using T = _underlying_set_;
   static T op(const T& a, const T& b) { return _a_op_b_; }
   static constexpr T identity() { return _identity_element_; }
   };
   */

/*
   struct MM {
   using OperatorMonoid = _operator_monoid_;
   using DataMonoid = _data_monoid_;
   static T act(const OperatorMonoid::T& m, const T& a) { return _m_act_a; }
   };
   */

template<class MM>
struct LazySegTree {
  private:
    using DM = typename MM::DataMonoid;
    using OM = typename MM::OperatorMonoid;
    using DT = typename DM::T;
    using OT = typename OM::T;
    const int n, h;
    vector<DT> data;
    vector<OT> lazy; // act

    void propFrom(int i, int sz) {
      if(lazy[i] == OM::identity()) return;
      data[i] = MM::act(lazy[i], sz, data[i]);
      if(i < n) {
        lazy[i * 2] = OM::op(lazy[i], lazy[i * 2]);
        lazy[i * 2 + 1] = OM::op(lazy[i], lazy[i * 2 + 1]);
      }
      lazy[i] = OM::identity();
    }

    void propToO(int i) {
      i += n;
      for(int j = h - 1; j >= 0; j--) propFrom(i >> j, 1 << j);
    }

    void propToD(int i) {
      i += n;
      int sz = 1;
      while(i >>= 1) propFrom(i * 2, sz), propFrom(i * 2 + 1, sz), //// important!!!
        data[i] = DM::op(data[i * 2], data[i * 2 + 1]), sz <<= 1;
    }

    void propToDataOne(int i) {
      data[i] = DM::op(data[i * 2], data[i * 2 + 1]);
    }

    int log(int x) {
      int h = 0;
      while(x >> h) h++;
      return h;
    }

  public:
    LazySegTree(int n, const DT& v = DM::identity(), const OT& w = OM::identity())
      : n(n), h(log(n)), data(2 * n, v), lazy(2 * n, w) {}

    template <class InputIt>
      LazySegTree(InputIt first, InputIt last)
      : n(distance(first, last)), h(log(n)),
      data(2 * n, DM::identity()), lazy(2 * n, OM::identity()) {
        copy(first, last, begin(data) + n);
        // たぶん深いところから更新するため
        for(int i = n; i > 0; i--) propToDataOne(i);
      }

    void act(int l, int r, const OT& m) {
      // なんか交換律を必要としないためにやっているのに,
      // 後半は完全に交換律を必用とする実装になっている感じがする
      l = max(0, l); r = min(r, n);
      propToO(l);
      propToO(r - 1);
      int tl = l, tr = r;
      int sz = 1;
      for(l += n, r += n; l < r; l >>= 1, r >>= 1, sz <<= 1) {
        if(l & 1) propFrom(l, sz), lazy[l] = m, propFrom(l, sz), l++;
        if(r & 1) --r, propFrom(r, sz), lazy[r] = m, propFrom(r, sz);
      }
      propToD(tl);
      propToD(tr - 1);
    }

    void set(int i, const DT& v) {
      propToO(i);
      data[i] = v;
      propToD(i);
    }

    DT get(int i) {
      propToO(i);
      return data[i + n];
    }

    DT query(int l, int r) {
      l = max(0, l); r = min(r, n);
      propToO(l);
      propToO(r - 1);
      DT tmpL = DM::identity(), tmpR = DM::identity();
      int sz = 1;
      for(l += n, r += n; l < r; l >>= 1, r >>= 1, sz <<= 1) {
        if(l & 1) propFrom(l, sz), tmpL = DM::op(tmpL, data[l++]);
        if(r & 1) propFrom(--r, sz), tmpR = DM::op(data[r], tmpR);
      }
      return DM::op(tmpL, tmpR);
    }

    void dum() {
#ifdef dump
      dump("data");
      dump(data);
      dump("op");
      dump(lazy);
#endif
    }
};

struct RangeMin {
  using T = long long;
  static T op(const T& a, const T& b) { return min(a, b); }
  static constexpr T identity() { return numeric_limits<T>::max(); }
};

struct RangeMax {
  using T = long long;
  static T op(const T& a, const T& b) { return max(a, b); }
  static constexpr T identity() { return numeric_limits<T>::min(); }
};

struct RangeSum {
  using T = long long;
  static T op(const T& a, const T& b) { return a + b; }
  static constexpr T identity() { return 0; }
};

struct RangeSet {
  using T = long long;
  static T op(const T& a, const T&) { return a; }
  static constexpr T identity() { return -1; }
};

/// }}}--- ///

// ex)

struct RangeMinAdd {
  using OperatorMonoid = RangeSum;
  using DataMonoid = RangeMin;
  static DataMonoid::T act(const OperatorMonoid::T& m, const DataMonoid::T& a) { return m + a; }
};

struct RangeSumAdd {
  using OperatorMonoid = RangeSum;
  using DataMonoid = RangeSum;
  static DataMonoid::T act(const OperatorMonoid::T& m, int sz, const DataMonoid::T& a) { return m * sz + a; }
};


int main() {
  ios::sync_with_stdio(false), cin.tie(0);
  int n, q;
  cin >> n >> q;
  int m = 1;
  while(m < n) m <<= 1;
  LazySegTree<RangeSumAdd> seg(m, 0, 0);
  while(q--) {
    int p, s, t;
    cin >> p >> s >> t;
    s--;
    if(!p) { // set
      ll x;
      cin >> x;
      seg.act(s, t, x);
      seg.dum();
    } else { // min
      cout << seg.query(s, t) << endl;
      seg.dum();
    }
  }
}



Measured memory_bytes: 6952