#include <iostream>
#include <vector>
#include <climits>
#include <functional>

template<typename T>
struct segment_tree {
    long long N; // 木の頂点数
    long long M; // 葉の数
    std::vector<T> V; // セグメント木　1-indexed
	std::vector<T> W; // 遅延配列　1-indexed
	std::vector<bool> flag; // true : W[i] の子孫に更新していない遅延配列が存在
    std::function<T(T, T)> op1; // 二項演算
	std::function<T(T, T, T)> op2; // 遅延伝播用の二項演算
	std::function<T(T, T)> op3; // 遅延配列更新用の二項演算
    T id1; // 単位元
	T id2; // 遅延伝播用の単位元

    // ===============================================================

    segment_tree(
		std::vector<T>& a,
		std::function<T(T, T)> f,
		std::function<T(T, T, T)> g,
		std::function<T(T, T)> h,
		T t1, T t2
	) : op1(f), op2(g), op3(h), id1(t1), id2(t2) {
        M = 1;
        while (M < a.size()) M *= 2;
        N = 2 * M;
        V.resize(N, id1); W.resize(N, id2); flag.resize(N, false);
        for (long long i = 0; i < a.size(); i++) V[M + i] = a[i];
        for (long long i = M - 1; i > 0; i--) {
            V[i] = op1(V[2 * i], V[2 * i + 1]);
        }
    }

    segment_tree() {}

    // ===============================================================

    void init(
		std::vector<T>& a,
		std::function<T(T, T)> f,
		std::function<T(T, T, T)> g,
		std::function<T(T, T)> h,
		T t1, T t2
	) {
        op1 = f; op2 = g; op3 = h; id1 = t1; id2 = t2;
		M = 1;
        while (M < a.size()) M *= 2;
        N = 2 * M;
        V.resize(N, id1); W.resize(N, id2); flag.resize(N, false);
        for (long long i = 0; i < a.size(); i++) V[M + i] = a[i];
        for (long long i = M - 1; i > 0; i--) {
            V[i] = op1(V[2 * i], V[2 * i + 1]);
        }
    }

	void laze_eval(long long cur_node, long long width) {
		if (W[cur_node] != id2) {
			V[cur_node] = op2(V[cur_node], W[cur_node], width);
			if (width > 1) {
				W[cur_node * 2] = op3(W[cur_node * 2], W[cur_node]);
				W[cur_node * 2 + 1] = op3(W[cur_node * 2 + 1], W[cur_node]);
			}
			W[cur_node] = id2;
		}
	}

	void range_update(
		long long l, long long r, T x,
		long long cur_node = 1,
		long long cur_left = 0, long long cur_right = -1
	) {
		if (cur_right == -1) cur_right = M;
		long long width = cur_right - cur_left;
		if (cur_right <= l || r <= cur_left) return;
		if (l <= cur_left && cur_right <= r) {
			W[cur_node] = op3(W[cur_node], x);
		}
		else {
			laze_eval(cur_node, width);
			flag[cur_node] = true;
			long long mid = (cur_left + cur_right) / 2;
			range_update(l, r, x, cur_node * 2, cur_left, mid);
			range_update(l, r, x, cur_node * 2 + 1, mid, cur_right);
			V[cur_node] = op1(V[cur_node * 2], V[cur_node * 2 + 1]);
		}
	}

	T range_fold(
		long long l, long long r,
		long long cur_node = 1,
		long long cur_left = 0, long long cur_right = -1
	) {
		if (cur_right == -1) cur_right = M;
		long long width = cur_right - cur_left;
		if (cur_right <= l || r <= cur_left) return id1;
		laze_eval(cur_node, width);
		if (width == 1) {
			flag[cur_node] = false;
			return V[cur_node];
		}
		long long mid = (cur_left + cur_right) / 2;
		if (l <= cur_left && cur_right <= r && !flag[cur_node]) {
			return V[cur_node];
		}
		else if (l <= cur_left && cur_right <= r) {
			flag[cur_node] = false;
			range_fold(cur_left, mid);
			range_fold(mid, cur_right);
			return V[cur_node] = op1(V[cur_node * 2], V[cur_node * 2 + 1]);
		}
		return op1(
			range_fold(l, r, cur_node * 2, cur_left, mid),
			range_fold(l, r, cur_node * 2 + 1, mid, cur_right)
		);
	}
};

int main() {
	long long n, q;
	std::cin >> n >> q;
	std::vector<long long> a(n, 0);

	auto f = [] (long long x, long long y) {return std::min(x, y);};
	auto g = [] (long long x, long long y, long long z) {return x + y;};
	auto h = [] (long long x, long long y) {return x + y;};
	segment_tree<long long> sg(a, f, g, h, LLONG_MAX, 0);

	while (q--) {
		long long z, s, t;
		std::cin >> z >> s >> t;
		if (z == 0) {
			long long x;
			std::cin >> x;
			sg.range_update(s, t + 1, x);
		}
		else std::cout << sg.range_fold(s, t + 1) << '\n';
	}
}


Measured memory_bytes: 7820