#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

/* attention
    long longのシフト演算には気をつけよう
    タイポした時のデバッグが死ぬほどきつくなるので変数名は最低3字くらい使った方がいいかも
    sizeは(int)とキャストしよう
    ごちゃごちゃ場合分けを考える前に全探索は考えましたか？
*/

const ll mod = 1e9+7;

void chmod(ll &M){
    if(M >= mod) M %= mod;
    else if(M < 0){
        M += (abs(M)/mod + 1)*mod;
        M %= mod;
    }
}

ll modpow(ll x, ll n){
    if(n == 0) return 1;

    ll res = modpow(x, n/2);
    if(n%2 == 0) return res*res%mod;
    else return res*res%mod*x%mod;
}

ll power(ll x, ll n){
    if(n == 0) return 1;

    ll res = power(x, n/2);
    if(n%2 == 0) return res*res;
    else return res*res*x;
}

int getl(int i, int N) { return i==0? N-1:i-1; };
int getr(int i, int N) { return i==N-1? 0:i+1; };

/* <--------------------------------------------> */


struct LazySegmentTree{
private:
    int n;
    vector<ll> node, lazy;

public:
    LazySegmentTree(const vector<ll> &v){
        int sz = (int)v.size();
        n = 1;
        while(n < sz) n *= 2;
        node.resize(2*n-1);
        lazy.resize(2*n-1, 0);

        for(int i=0; i<sz; ++i) node[i+n-1] = v[i];
        for(int i=n-2; i>=0; --i) node[i] = node[i*2+1] + node[i*2+2];
    }

    // 遅延評価
    // 自ノードの値配列に値を伝播させる
    // 子ノードの遅延配列に値を伝播させる
    // k番目のノードについて遅延評価を行う
    void eval(int k, int l, int r){
        // 遅延配列が空でない場合、自ノード及び子ノードへの値の伝播が起こる
        if(lazy[k] != 0){
            node[k] += lazy[k];

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

            // 伝播が終わったので、自ノードの遅延配列を空にする
            lazy[k] = 0;
        }
    }

    // [a,b)にxを加算, kは今見ているノードの番号で区間[l,r)に対応している
    void add(int a, int b, ll 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);
            node[k] = node[2*k+1] + node[2*k+2];
        }
    }

    // 区間和の更新
    ll getsum(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 node[k];
        ll vl = getsum(a, b, 2*k+1, l, (l+r)/2);
        ll vr = getsum(a, b, 2*k+2, (l+r)/2, r);
        return vl + vr;
    }
};

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);

    int n, q; cin >> n >> q;
    LazySegmentTree seg(vector<ll>(n, 0));

    for(int i=0; i<q; ++i){
        int c; cin >> c;
        if(c == 0){
            int s, t, x;
            cin >> s >> t >> x;
            seg.add(s-1, t, x);
        }
        else{
            int s, t; cin >> s >> t;
            cout << seg.getsum(s-1, t) << endl;
        }
    }

	return 0;
}



Measured memory_bytes: 7868