using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using SB = System.Text.StringBuilder;
//using System.Text.RegularExpressions;
//using System.Globalization;
//using System.Diagnostics;
using static System.Console;
using System.Numerics;
using static System.Math;
using pair = Pair<int, int>;

class Program
{
    static void Main()
    {
        SetOut(new StreamWriter(OpenStandardOutput()) { AutoFlush = false });
        new Program().solve();
        Out.Flush();
    }
    readonly Scanner cin = new Scanner();
    readonly int[] dd = { 0, 1, 0, -1, 0 }; //→↓←↑
    readonly int mod = 1000000007;
    readonly int dom = 998244353;
    bool chmax<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) < 0) { a = b; return true; } return false; }
    bool chmin<T>(ref T a, T b) where T : IComparable<T> { if (b.CompareTo(a) < 0) { a = b; return true; } return false; }

    void solve()
    {
        int N = cin.nextint;
        int Q = cin.nextint;
        var S = new LazySegtree<int, int>(N, Min, (x, y, len) => x + y, (x, y) => x + y, int.MaxValue, 0);
        for (int i = 0; i < Q; i++)
        {
            int com = cin.nextint;
            if (com == 0)
            {
                S.Update(cin.nextint, cin.nextint, cin.nextint);
            }
            else if (com == 1)
            {
                WriteLine(S[cin.nextint, cin.nextint]);
            }
        }
    }

}

/// <OriginalAuthor>riantkb</OriginalAuthor>
class LazySegtree<T, U>
{
    readonly int n;
    T[] data;
    U[] lazy;
    readonly bool[] is_lazy;
    readonly Func<T, T, T> calc;
    readonly Func<T, U, int, T> apply;
    readonly Func<U, U, U> merge;
    readonly T ex_data;

    /// <summary>
    /// 遅延セグメントツリーの構築
    /// </summary>
    /// <param name="m">要素数</param>
    /// <param name="calc">要素のマージ</param>
    /// <param name="apply">要素に作用素を作用</param>
    /// <param name="merge">作用素のマージ</param>
    /// <param name="ex_data">単位元</param>
    public LazySegtree(int m, Func<T, T, T> calc, Func<T, U, int, T> apply, Func<U, U, U> merge, T ex_data)
    {
        this.calc = calc;
        this.apply = apply;
        this.merge = merge;
        this.ex_data = ex_data;
        n = 1;
        while (n < m) n <<= 1;
        data = new T[n * 2 - 1];
        lazy = new U[n * 2 - 1];
        is_lazy = new bool[n * 2 - 1];
        for (int i = 0; i < data.Length; i++) data[i] = ex_data;
    }
    public LazySegtree(int m, Func<T, T, T> calc, Func<T, U, int, T> apply, Func<U, U, U> merge, T ex_data, T ini) : this(m, calc, apply, merge, ex_data)
    {
        for (int i = 0; i < m; i++) data[i + n - 1] = ini;
        for (int i = n - 2; i >= 0; i--) data[i] = calc(data[i * 2 + 1], data[i * 2 + 2]);
    }
    public LazySegtree(int m, Func<T, T, T> calc, Func<T, U, int, T> apply, Func<U, U, U> merge, T ex_data, IList<T> ini) : this(m, calc, apply, merge, ex_data)
    {
        for (int i = 0; i < m; i++) data[i + n - 1] = ini[i];
        for (int i = n - 2; i >= 0; i--) data[i] = calc(data[i * 2 + 1], data[i * 2 + 2]);
    }
    void assign_lazy(int k, U x)
    {
        if (k >= lazy.Length) return;
        if (is_lazy[k]) lazy[k] = merge(lazy[k], x);
        else
        {
            is_lazy[k] = true;
            lazy[k] = x;
        }
    }
    void eval(int k, int len)
    {
        if (!is_lazy[k]) return;
        assign_lazy(k * 2 + 1, lazy[k]);
        assign_lazy(k * 2 + 2, lazy[k]);
        data[k] = apply(data[k], lazy[k], len);
        is_lazy[k] = false;
    }
    T update(int s, int t, U x, int k, int l, int r)
    {
        eval(k, r - l);
        if (r <= s || t <= l) return data[k];
        if (s <= l && r <= t)
        {
            assign_lazy(k, x);
            return apply(data[k], lazy[k], r - l);
        }
        return data[k] = calc(update(s, t, x, k * 2 + 1, l, (l + r) / 2),
                              update(s, t, x, k * 2 + 2, (l + r) / 2, r));
    }
    T run(int s, int t, int k, int l, int r)
    {
        eval(k, r - l);
        if (r <= s || t <= l) return ex_data;
        if (s <= l && r <= t) return data[k];
        return calc(run(s, t, k * 2 + 1, l, (l + r) / 2),
                    run(s, t, k * 2 + 2, (l + r) / 2, r));
    }

    /// <summary>update [s, t]</summary>
    public void Update(int s, int t, U x) { t++; update(s, t, x, 0, 0, n); }
    /// <summary>return node[s, t]</summary>
    public T this[int s, int t] => Run(s, t);
    T Run(int s, int t) { t++; return run(s, t, 0, 0, n); }
}

static class Ex
{
    public static void join<T>(this IEnumerable<T> values, string sep = " ") => WriteLine(string.Join(sep, values));
    public static string concat<T>(this IEnumerable<T> values) => string.Concat(values);
    public static string reverse(this string s) { var t = s.ToCharArray(); Array.Reverse(t); return t.concat(); }

    public static int lower_bound<T>(this IList<T> arr, T val) where T : IComparable<T>
    {
        int low = 0, high = arr.Count;
        int mid;
        while (low < high)
        {
            mid = ((high - low) >> 1) + low;
            if (arr[mid].CompareTo(val) < 0) low = mid + 1;
            else high = mid;
        }
        return low;
    }
    public static int upper_bound<T>(this IList<T> arr, T val) where T : IComparable<T>
    {
        int low = 0, high = arr.Count;
        int mid;
        while (low < high)
        {
            mid = ((high - low) >> 1) + low;
            if (arr[mid].CompareTo(val) <= 0) low = mid + 1;
            else high = mid;
        }
        return low;
    }
}

class Pair<T, U> : IComparable<Pair<T, U>> where T : IComparable<T> where U : IComparable<U>
{
    public T f; public U s;
    public Pair(T f, U s) { this.f = f; this.s = s; }
    public int CompareTo(Pair<T, U> a) => f.CompareTo(a.f) != 0 ? f.CompareTo(a.f) : s.CompareTo(a.s);
    public override string ToString() => $"{f} {s}";
}

class Scanner
{
    string[] s; int i;
    readonly char[] cs = new char[] { ' ' };
    public Scanner() { s = new string[0]; i = 0; }
    public string[] scan => ReadLine().Split();
    public int[] scanint => Array.ConvertAll(scan, int.Parse);
    public long[] scanlong => Array.ConvertAll(scan, long.Parse);
    public double[] scandouble => Array.ConvertAll(scan, double.Parse);
    public string next
    {
        get
        {
            if (i < s.Length) return s[i++];
            string st = ReadLine();
            while (st == "") st = ReadLine();
            s = st.Split(cs, StringSplitOptions.RemoveEmptyEntries);
            i = 0;
            return next;
        }
    }
    public int nextint => int.Parse(next);
    public long nextlong => long.Parse(next);
    public double nextdouble => double.Parse(next);
}



Measured memory_bytes: 21668