#include "bits/stdc++.h"
using namespace std;
#define mod 1000000007
#define dom 998244353
#define all(c) begin(c),end(c)
#define rep(i,n) repi(i,0,n)
#define repi(i,a,b) for(int i=(a);i<(b);i++)
#define rrep(i,a,b) for(int i=(b)-1;i>=(a);i--)
template <typename T> bool chmax(T &a, const T &b) { if (a < b) { a = b; return true; } return false; }
template <typename T> bool chmin(T &a, const T &b) { if (b < a) { a = b; return true; } return false; }
#define long long long
#define List vector
#define var auto
#define Count size()
#define Length size()
int dd[] = { 0, 1, 0, -1, 0 }; //→↓←↑

template <typename T, typename U>
struct LazySegTree {
	int n;
	function<T(T, T)> calc;
	function<T(T, U, int)> apply;
	function<U(U, U)> merge;
	T ex;
	vector<T> data;
	vector<U> lazy;
	vector<bool> is_lazy;
	LazySegTree(int n_, function<T(T, T)> calc,
		function<T(T, U, int)> apply,
		function<U(U, U)> merge,
		T ex){
		this->calc = calc;
		this->apply = apply;
		this->merge = merge;
		this->ex = ex;	
		init(n_);
	}
	void init(int n_) {
		n = 1;
		while (n < n_) n *= 2;
		data.clear();
		data.resize(2 * n - 1, ex);
		lazy.clear();
		lazy.resize(2 * n - 1, U());
		is_lazy.clear();
		is_lazy.resize(2 * n - 1, false);
	}
	void assign_lazy(int k, U x)
	{
		if (k >= (int)lazy.size()) return;
		if (is_lazy[k]) lazy[k] = merge(lazy[k], x);
		else
		{
			is_lazy[k] = true;
			lazy[k] = x;
		}
	}
	void eval(int len, int k) {
		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 a, int b, U x, int k, int l, int r) {
		eval(r - l, k);
		if (r <= a || b <= l) return data[k];
		if (a <= l && r <= b) {
			assign_lazy(k, x);
			return apply(data[k], lazy[k], r - l);
		}
		return data[k] = calc(update(a, b, x, k * 2 + 1, l, (l + r) / 2),
			update(a, b, x, k * 2 + 2, (l + r) / 2, r));
	}
	// [a, b]に対する閉区間更新 0-indexed
	T update(int a, int b, U x) {
		b++;
		return update(a, b, x, 0, 0, n);
	}
	T query(int a, int b, int k, int l, int r) {
		eval(r - l, k);
		if (r <= a || b <= l) return ex;
		if (a <= l && r <= b) return data[k];
		T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
		T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
		return calc(vl, vr);
	}
	// return node [a,b] 閉区間クエリ 0-indexed
	T query(int a, int b) {
		b++;
		return query(a, b, 0, 0, n);
	}

	//デバッグ用
	vector<T> items()
	{
		vector<T> ret(n);
		for (int i = 0; i < n; i++)
		{
			ret[i] = query(i, i);
		}
		return ret;
	}
};
//呼び出し方
//区間Add区間Sum
//LazySegTree<int, int> raq_rsq(N,
//	[](int a, int b) { return a + b; },
//	[](int a, int b, int len) { return a + b * len; },
//	[](int a, int b) { return a + b; },
//	0);
//区間変更区間Min
//LazySegTree<int, int> ruq_rmq(N,
//	[](int a, int b) { return min(a, b); },
//	[](int a, int b, int len) {return b; },
//	[](int a, int b) {return b; },
//	INT_MAX);

void solve()
{
	int N, Q;
	cin >> N >> Q;

	LazySegTree<long, long> raq_rsq(N,
	[](long a, long b) { return a + b; },
	[](long a, long b, int len) { return a + b * len; },
	[](long a, long b) { return a + b; },
	0);
	rep(i, Q)
	{
		int com;
		cin >> com;
		if (com == 0)
		{
			int s, t, x;
			cin >> s >> t >> x;
			s--; t--;
			raq_rsq.update(s, t, x);
		}
		else
		{
			int s, t;
			cin >> s >> t;
			s--; t--;
			cout << raq_rsq.query(s, t) << endl;
		}
	}
	//auto p = raq.items();
	//rep(i, p.size())
	//{
	//	cout << p[i] << " ";
	//}
}

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



Measured memory_bytes: 7204