#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;


/* Utils */

inline bool curSegmInQuerySegm (size_t query_l, size_t query_r, size_t cur_l, size_t cur_r) {
	return (query_l <= cur_l && cur_r <= query_r);
}

inline bool curSegmOutQuerySegm (size_t query_l, size_t query_r, size_t cur_l, size_t cur_r) {
	return (cur_r < query_l || query_r < cur_l);
}


/* Segment Tree Class */

class SegmentTree {
	private:
		struct Node {
			size_t left;
			size_t right;
			Node* left_tree;
			Node* right_tree;
			int minimum;
			int add;
		
			Node (size_t left, size_t right, int minimum = neutral) {
				this->left = left;
				this->right = right;
				this->left_tree = nullptr;
				this->right_tree = nullptr;
				this->minimum = minimum;
				this->add = 0;
			}

			void push ();
		} *root;
	
		const static int neutral = 1000000000;
		vector<int> arr;

		int buildTree (Node *node);
		int minOnSubsegment (size_t l, size_t r, Node *node);
		void addOnSubsegment (size_t l, size_t r, int value, Node *node);
	
	public:
		SegmentTree (const vector<int> &arr);
		int RMQ (size_t l, size_t r);
		void RAQ (size_t l, size_t r, int minimum);

		void print (Node *node = nullptr) {
			if (node == nullptr)
				node = root;

			if (node->left_tree)
				print(node->left_tree);

			if (node->right_tree)
				print(node->right_tree);
		}

		void getArray () {
			for(int i = 0; i < arr.size(); i ++)
				cout << RMQ(i, i) << " ";

			cout << endl;
		}
};


/* Main methods: */

SegmentTree::SegmentTree(const vector<int> &arr) {
	this->arr = arr;
	root = new Node(0, arr.size() - 1);
	buildTree(root);
}

int SegmentTree::buildTree(Node *node) {
	if (node->left == node->right) {
		node->left_tree = nullptr; //На всякий случай
		node->right_tree = nullptr; //На всякий случай
		return node->minimum = arr[node->left];
	}

	size_t half = node->left + (node->right - node->left) / 2;
	node->left_tree = new Node(node->left, half);
	node->right_tree = new Node(half + 1, node->right);
	int left_min = buildTree(node->left_tree);
	int right_min = buildTree(node->right_tree);
	return node->minimum = min(left_min, right_min);
}

void SegmentTree::Node::push () {
	if (add == 0)
		return;
	
	if (left_tree)
		left_tree->add += add;
	
	if (right_tree)
		right_tree->add += add;

	minimum += add;
	add = 0;
}


/* Subsegment methods: */

int SegmentTree::minOnSubsegment (size_t l, size_t r, Node *node) {
	if (!node)
		return neutral;

	node->push();

	if (curSegmInQuerySegm(l, r, node->left, node->right))
		return node->minimum;

	if (!curSegmOutQuerySegm(l, r, node->left, node->right))
		return min(minOnSubsegment(l, r, node->left_tree), minOnSubsegment(l, r, node->right_tree));

	return neutral;
}

void SegmentTree::addOnSubsegment (size_t l, size_t r, int add, Node *node) {
	if (!node)
		return;

	node->push();

	if (curSegmInQuerySegm(l, r, node->left, node->right)) {
		node->add += add;
		node->push();
		return;
	}

	if (!curSegmOutQuerySegm(l, r, node->left, node->right)) {
		addOnSubsegment(l, r, add, node->left_tree);
		addOnSubsegment(l, r, add, node->right_tree);
		node->minimum = std::min<int>(node->left_tree->minimum, node->right_tree->minimum);
	}
}


/* User subsegment methods: */

int SegmentTree::RMQ (size_t l, size_t r) {
	return minOnSubsegment(l, r, root);
}

void SegmentTree::RAQ (size_t l, size_t r, int add) {
	addOnSubsegment(l, r, add, root);
}


/* Solving problem: */

int main() {
	int n, q;
	cin >> n >> q;
	vector<int> arr(n, 0);

	SegmentTree segmentTree(arr);
	//segmentTree.print();

	for (int i = 0; i < q; i ++) {
		int type;
		cin >> type;

		if (type == 0) {
			size_t l, r;
			int add;
			cin >> l >> r >> add;
			segmentTree.RAQ(l, r, add);
		}

		else {
			size_t l, r;
			cin >> l >> r;
			cout << segmentTree.RMQ(l, r) << endl;
		}
	}

	return 0;
}



Measured memory_bytes: 12896