using System;
using System.Collections.Generic;
using System.Linq;
using static System.Console;
using static System.Math;

class Program
{
    static void Main()
    {
        var nq = ReadLine().Split().Select(int.Parse).ToArray();
        var n = nq[0];
        var q = nq[1];
        var segtree = new LazySegmentTree(n, (x, y) => x + y, 0);
        for (int i = 0; i < q; i++)
        {
            var com = ReadLine().Split().Select(int.Parse).ToArray();
            if (com[0] == 0)
            {
                segtree.Add(com[1] - 1, com[2], com[3]);
            }
            else
            {
                WriteLine(segtree.Query(com[1] - 1, com[2]));
            }
        }
    }
}

public class LazySegmentTree//未実装 RAQ or RUQ
{
    long[] buffer;
    long[] lazy;
    int N;
    long IE;
    Func<long, long, long> Op;

    public LazySegmentTree(int cap, Func<long, long, long> op, long E)
    {
        var c = 1;
        while (c < cap) c <<= 1;

        N = c;
        buffer = new long[N * 2 - 1];
        lazy = new long[N * 2 - 1];
        for (int i = 0; i < buffer.Length; i++) buffer[i] = E;
        Op = op;
        IE = E;
    }

    public LazySegmentTree(int[] init, Func<long, long, long> op, int E)
    {
        var c = 1;
        while (c < init.Length) c <<= 1;

        N = c;
        buffer = new long[N * 2 - 1];
        lazy = new long[N * 2 - 1];

        Array.Copy(init, 0, buffer, N - 1, init.Length);
        for (int i = init.Length + N - 1; i < buffer.Length; i++) buffer[i] = E;
        for (int i = N - 2; i >= 0; i--)
        {
            buffer[i] = op(buffer[i * 2 + 1], buffer[i * 2 + 2]);
        }
        Op = op;
        IE = E;
    }

    public void Update(int index, long value)
    {
        index += N - 1;
        buffer[index] = value;
        while (index > 0)
        {
            index = (index - 1) >> 1;
            buffer[index] = Op(buffer[index * 2 + 1], buffer[index * 2 + 2]);
        }
    }

    public long this[int index]
    {
        set
        {
            Update(index, value);
        }
        get
        {
            return buffer[index + N - 1];
        }
    }

    void Eval(int k, int l, int r)
    {

        // 遅延配列が空でない場合、自ノード及び子ノードへの
        // 値の伝播が起こる
        if (lazy[k] != 0)
        {
            buffer[k] += lazy[k];

            // 最下段かどうかのチェックをしよう
            // 子ノードは親ノードの 1/2 の範囲であるため、
            // 伝播させるときは半分にする
            if (r - l > 1)
            {
                lazy[2 * k + 1] += lazy[k] / 2;
                lazy[2 * k + 2] += lazy[k] / 2;
            }

            // 伝播が終わったので、自ノードの遅延配列を空にする
            lazy[k] = 0;
        }
    }
    public void Add(int a, int b, long x, int k = 0, int l = 0, int r = -1)
    {
        if (r < 0) r = N;

        // k 番目のノードに対して遅延評価を行う
        Eval(k, l, r);

        // 範囲外なら何もしない
        if (b <= l || r <= a) return;

        // 完全に被覆しているならば、遅延配列に値を入れた後に評価//評価必要？
        if (a <= l && r <= b)
        {
            lazy[k] += (r - l) * x;
            Eval(k, l, r);
        }

        // そうでないならば、子ノードの値を再帰的に計算して、
        // 計算済みの値をもらってくる
        else
        {
            Add(a, b, x, 2 * k + 1, l, (l + r) / 2);
            Add(a, b, x, 2 * k + 2, (l + r) / 2, r);
            buffer[k] = buffer[2 * k + 1] + buffer[2 * k + 2];
        }
    }

    public long Query(int a, int b, int k = 0, int l = 0, int r = -1)
    {
        if (r < 0) r = N;
        if (b <= l || r <= a) return 0;

        // 関数が呼び出されたら評価！
        Eval(k, l, r);
        if (a <= l && r <= b) return buffer[k];
        var vl = Query(a, b, 2 * k + 1, l, (l + r) / 2);
        var vr = Query(a, b, 2 * k + 2, (l + r) / 2, r);
        return vl + vr;
    }
}



Measured memory_bytes: 26108