//#define NDEBUG
#define _CRT_SECURE_NO_WARNINGS
#include <array>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <limits>
#include <memory>
#include <string>
#include <type_traits>

template <class Integral> class Rirange;

template <class Integral = std::size_t> class irange {
public:
	using value_type = Integral;
	using reference = value_type &;
	using const_reference = const value_type &;
	class irangeitr {
		friend irange;
		value_type i;
		irangeitr(const value_type x) noexcept : i(x) {}

	public:
		void operator++() noexcept { ++i; }
		value_type &operator*() noexcept { return i; }
		const_reference operator*() const noexcept { return i; }
		bool operator!=(const irangeitr &x) const noexcept { return i < x.i; }
	};

private:
	const value_type f, l;

public:
	irange(const value_type first, const value_type last) noexcept
		: f(first), l(last) {}
	irangeitr begin() const noexcept { return irangeitr(f); }
	irangeitr end() const noexcept { return irangeitr(l); }
	Rirange<value_type> rev() const noexcept {
		return Rirange<value_type>(l - 1, f - 1);
	}
};
template <class Integral = std::size_t> class Rirange {
public:
	using value_type = Integral;
	using reference = value_type &;
	using const_reference = const value_type &;
	class Rirangeitr {
		friend Rirange;
		value_type i;
		Rirangeitr(const value_type x) noexcept : i(x) {}

	public:
		void operator++() noexcept { --i; }
		reference operator*() noexcept { return i; }
		const_reference operator*() const noexcept { return i; }
		bool operator!=(const Rirangeitr &x) const noexcept {
			return (!~x.i && ~i) || x.i < i;
		}
	};

private:
	const value_type f, l;

public:
	Rirange(const value_type x, const value_type y) noexcept : f(x), l(y) {}
	Rirangeitr begin() const noexcept { return Rirangeitr(f); }
	Rirangeitr end() const noexcept { return Rirangeitr(l); }
	irange<value_type> rev() const noexcept {
		return irange<value_type>(l + 1, f + 1);
	}
};

template <class T> bool maxi(T &a, const T &b) {
	if (b < a)
		return 0;
	a = b;
	return 1;
}
template <class T> bool mini(T &a, const T &b) {
	if (a < b)
		return 0;
	a = b;
	return 1;
}
template <class T> bool smaxi(T &a, const T &b) {
	if (a < b) {
		a = b;
		return 1;
	}
	return 0;
}
template <class T> bool smini(T &a, const T &b) {
	if (b < a) {
		a = b;
		return 1;
	}
	return 0;
}
struct customIO {
	int c;
	bool f;
	std::array<int, 30> buf;
	const std::array<int, 10> itoc;
	std::array<std::uint_least8_t, 256> ctoi_base;
	const std::uint_least8_t *const ctoi;
	void get_c() { c = fgetc(stdin); }
	void put_c(int x) { fputc(x, stdout); }
	bool vacant() { return c == ' ' || c == '\n'; }
	operator int() { return 0; }

	explicit customIO()
		: itoc({ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }),
		ctoi(std::addressof(ctoi_base[-static_cast<std::int_fast16_t>(
			std::numeric_limits<char>::min())])) {
		for (std::uint_least8_t i = 0; i < 10; ++i)
			ctoi_base[static_cast<int>("0123456789"[i]) -
			static_cast<std::int_fast16_t>(
				std::numeric_limits<char>::min())] = i;
	}
	// in

	void cueing() {
		while (get_c(), vacant())
			;
	}
	template <class T>
	auto operator>>(T &d) ->
		typename std::enable_if<std::is_signed<T>::value, customIO &>::type {
		d = 0;
		f = 0;
		cueing();
		if (c == '-')
			f = 1, get_c();
		do
			d = d * 10 + ctoi[c];
		while (get_c(), !vacant());
		if (f)
			d = -d;
		return *this;
	}
	template <class T>
	auto operator>>(T &d) ->
		typename std::enable_if<!std::is_signed<T>::value, customIO &>::type {
		d = 0;
		cueing();
		do
			d = d * 10 + ctoi[c];
		while (get_c(), !vacant());
		return *this;
	}
	customIO &operator>>(char &d) {
		cueing();
		d = c;
		return *this;
	}
	customIO &operator>>(double &d) {
		scanf("%lf", &d);
		return *this;
	}
	customIO &operator>>(std::string &d) {
		d.clear();
		cueing();
		do
			d.push_back(c);
		while (get_c(), !vacant());
		return *this;
	}
	template <class T> T input() {
		T d;
		*this >> d;
		return d;
	}

	// out

	template <class T>
	auto operator<<(T d) ->
		typename std::enable_if<std::is_signed<T>::value, customIO &>::type {
		c = 0;
		f = 0;
		if (d < static_cast<T>(0))
			f = 1, d = -d;
		while (d)
			buf[c++] = itoc[d % 10], d /= 10;
		if (!c)
			buf[c++] = itoc[0];
		if (f)
			put_c('-');
		while (c--)
			put_c(buf[c]);
		return *this;
	}
	template <class T>
	auto operator<<(T d) ->
		typename std::enable_if<!std::is_signed<T>::value, customIO &>::type {
		c = 0;
		while (d)
			buf[c++] = itoc[d % 10], d /= 10;
		if (!c)
			buf[c++] = itoc[0];
		while (c--)
			put_c(buf[c]);
		return *this;
	}
	customIO &operator<<(char d) {
		put_c(d);
		return *this;
	}
	customIO &operator<<(double d) {
		printf("%f", d);
		return *this;
	}
	customIO &operator<<(const std::string &d) {
		for (const auto e : d)
			put_c(e);
		return *this;
	}
	customIO &operator<<(const char *d) {
		while (*d != '\0')
			put_c(*(d++));
		return *this;
	}
	void endl() { put_c('\n'); }
	void space() { put_c(' '); }
} IO;

using int32 = std::int_fast32_t;
using int64 = std::int_fast64_t;
using uint32 = std::uint_fast32_t;
using uint64 = std::uint_fast64_t;
using intl32 = std::int_least32_t;
using intl64 = std::int_least64_t;
using uintl32 = std::uint_least32_t;
using uintl64 = std::uint_least64_t;
#include <cassert>
#include <functional>
#include <utility>
#include <vector>

template <typename ValueMonoid, typename OperatorMonoid, class Modify>
class LazySegmentTree {
public:
	using value_type = ValueMonoid;
	using reference = value_type &;
	using const_reference = const value_type &;
	using operator_type = OperatorMonoid;

private:
	using container_type = std::vector<std::pair<value_type, operator_type>>;

public:
	using size_type = typename container_type::size_type;

private:
	const Modify m;
	const size_type size_, height, capacity;
	container_type tree;
	static size_type getheight(const size_type &size) noexcept {
		size_type ret = 0;
		while (static_cast<size_type>(1) << ret < size)
			++ret;
		return ret;
	}
	value_type reflect(const size_type &index) {
		return m(tree[index].first, tree[index].second);
	}
	void recalc(const size_type &index) {
		tree[index].first = reflect(index << 1) + reflect(index << 1 | 1);
	}
	void assign(const size_type &index, const operator_type &data) {
		tree[index].second = tree[index].second + data;
	}
	void push(const size_type &index) {
		assign(index << 1, tree[index].second);
		assign(index << 1 | 1, tree[index].second);
		tree[index].second = operator_type();
	}
	void propagate(const size_type &index) {
		for (size_type i = height; i; --i)
			push(index >> i);
	}
	void thrust(const size_type &index) {
		tree[index].first = reflect(index);
		push(index);
	}
	void evaluate(const size_type &index) {
		for (size_type i = height; i; --i)
			thrust(index >> i);
	}
	void build(size_type index) {
		while (index >>= 1)
			recalc(index);
	}

public:
	explicit LazySegmentTree(const size_type &size, const Modify &m = Modify())
		: m(m), size_(size), height(getheight(size_)),
		capacity(static_cast<size_type>(1) << height), tree(capacity << 1) {}
	void update(size_type begin, size_type end, const operator_type &data) {
		assert(begin <= end);
		assert(begin <= size());
		assert(end <= size());
		begin += capacity;
		end += capacity;
		propagate(begin);
		propagate(end - 1);
		for (size_type left = begin, right = end; left < right;
			left >>= 1, right >>= 1) {
			if (left & 1)
				assign(left++, data);
			if (right & 1)
				assign(right - 1, data);
		}
		build(begin);
		build(end - 1);
	}
	void update(size_type index,
		const std::function<value_type(const_reference)> &f) {
		assert(index < size());
		index += capacity;
		propagate(index);
		tree[index].first = f(reflect(index));
		tree[index].second = operator_type();
		build(index);
	}
	void update(const size_type index, const_reference data) {
		assert(index < size());
		update(index, [&data](const_reference d) { return data; });
	}
	value_type range(size_type begin, size_type end) {
		assert(begin <= end);
		assert(begin <= size());
		assert(end <= size());
		begin += capacity;
		end += capacity;
		evaluate(begin);
		evaluate(end - 1);
		value_type retL, retR;
		for (; begin < end; begin >>= 1, end >>= 1) {
			if (begin & 1)
				retL = retL + reflect(begin++);
			if (end & 1)
				retR = reflect(end - 1) + retR;
		}
		return retL + retR;
	}
	size_type search(const std::function<bool(const_reference)> &b) {
		if (b(value_type()))
			return 0;
		if (!b(reflect(1)))
			return size() + 1;
		value_type acc;
		size_type i = 1;
		while (i < capacity) {
			thrust(i);
			if (!b(acc + reflect(i <<= 1)))
				acc = acc + reflect(i++);
		}
		return i - capacity + 1;
	}
	const_reference operator[](size_type index) {
		assert(index < size());
		index += capacity;
		evaluate(index);
		tree[index].first = reflect(index);
		tree[index].second = operator_type();
		return tree[index].first;
	}
	size_type size() const noexcept { return size_; }
	bool empty() const noexcept { return !size_; }
};

template <typename V, typename O, class F>
LazySegmentTree<V, O, F>
make_Lazy(const typename LazySegmentTree<V, O, F>::size_type &size,
	const F &f) {
	return LazySegmentTree<V, O, F>(size, f);
}
#include <algorithm>
#include <cstddef>
#include <limits>
#include <utility>

template <class T> struct Ass {
	using value_type = T;
	value_type a;
	bool f;
	Ass() : f(0) {}
	explicit Ass(const value_type &x) : a(x), f(1) {}
	explicit Ass(value_type &&x) : a(std::move(x)), f(1) {}
	Ass operator+(const Ass &o) const { return o.f ? o : *this; }
};

template <class T> struct Add {
	using value_type = T;
	value_type a;
	Add() : a(0) {}
	explicit Add(const value_type &x) : a(x) {}
	explicit Add(value_type &&x) : a(std::move(x)) {}
	Add operator+(const Add &o) const { return Add(a + o.a); }
};

template <class T> struct Mini {
	using value_type = T;
	value_type a;
	Mini() : a(std::numeric_limits<value_type>::max()) {}
	explicit Mini(const value_type &x) : a(x) {}
	explicit Mini(value_type &&x) : a(std::move(x)) {}
	Mini operator+(const Mini &o) const { return Mini(std::min(a, o.a)); }
	Mini operator*(const Ass<value_type> &o) const {
		return o.f ? Mini(o.a) : *this;
	}
	Mini operator*(const Add<value_type> &o) const { return Mini(a + o.a); }
};

template <class T> struct Maxi {
	using value_type = T;
	value_type a;
	Maxi() : a(std::numeric_limits<value_type>::min()) {}
	explicit Maxi(const value_type &x) : a(x) {}
	explicit Maxi(value_type &&x) : a(std::move(x)) {}
	Maxi operator+(const Maxi &o) const { return Maxi(std::max(a, o.a)); }
	Maxi operator*(const Ass<value_type> &o) const {
		return o.f ? Maxi(o.a) : *this;
	}
	Maxi operator*(const Add<value_type> &o) const { return Maxi(a + o.a); }
};

template <class T> struct Sum {
	using value_type = T;
	using size_type = std::size_t;
	value_type a;
	size_type s;
	Sum() : a(0), s(0) {}
	explicit Sum(const value_type &x, const size_type y) : a(x), s(y) {}
	explicit Sum(value_type &&x, const size_type y) : a(std::move(x)), s(y) {}
	Sum operator+(const Sum &o) const { return Sum(a + o.a, s + o.s); }
	Sum operator*(const Ass<value_type> &o) const {
		return o.f ? Sum(o.a * s, s) : *this;
	}
	Sum operator*(const Add<value_type> &o) const { return Sum(a + o.a * s, s); }
};

template<class T,class U>
struct multi {
	T operator()(const T &x, const U &y)const {
		return x*y;
	}
};
int main() {
	using S = Sum<int64>;
	using A = Ass<int64>;
	const auto n = IO.input<uint32>();
	uint32 q;
	IO >> q;
	LazySegmentTree<S, A, multi<S, A>> T(n);
	for (const auto i : irange<>(0, n))
		T.update(i, S(0, 1));
	uint32 c, s, t;
	int64 x;
	while (q--) {
		IO >> c >> s >> t;
		if (c)
			IO << T.range(s, t + 1).a << '\n';
		else
			IO >> x, T.update(s, t + 1, A(x));
	}
	return 0;
}


Measured memory_bytes: 10500