#define _CRT_SECURE_NO_WARNINGS
#define NDEBUG
#include <array>
#include <bitset>
#include <cassert>
#include <memory>

template <::std::size_t Bitlength, class Size = ::std::size_t>
class binary_trie {
public:
	using value_type = ::std::bitset<Bitlength>;
	using size_type = Size;

private:
	class node_type {
	public:
		::std::array<::std::unique_ptr<node_type>, 2> child;
		typename binary_trie::size_type size;
		node_type() : size(0) {}
	};
	using pointer = ::std::unique_ptr<node_type>;
	using const_pointer = ::std::unique_ptr<const node_type>;
	value_type lazy;
	pointer root;
	static size_type size(const node_type *const ptr) noexcept {
		return ptr ? ptr->size : size_type(0);
	}

public:
	binary_trie() : lazy(), root() {}

	bool empty() const noexcept { return !root; }
	size_type size() const noexcept { return size(root.get()); }

	size_type count(const value_type &x) const {
		::std::size_t i = Bitlength;
		const node_type *ptr = root.get();
		while (ptr && i--)
			ptr = ptr->child[x.test(i) ^ lazy.test(i)].get();
		return size(ptr);
	}
	value_type find_by_order(size_type k) const {
		assert(k < size());
		value_type ret;
		::std::size_t i = Bitlength;
		const node_type *ptr = root.get();
		while (i--) {
			if (size(ptr->child[lazy.test(i)].get()) <= k) {
				k -= size(ptr->child[lazy.test(i)].get());
				ptr = ptr->child[lazy.test(i) ^ 1].get();
				ret.set(i);
			}
			else {
				ptr = ptr->child[lazy.test(i)].get();
			}
		}
		return ret;
	}
	size_type order_of_key(const value_type &x) const {
		assert(count(x));
		size_type ret = 0;
		::std::size_t i = Bitlength;
		const node_type *ptr = root.get();
		while (i--) {
			if (x.test(i) ^ lazy.test(i)) {
				ret += size(ptr->child[lazy.test(i)].get());
				ptr = ptr->child[lazy.test(i) ^ 1].get();
			}
			else {
				ptr = ptr->child[lazy.test(i)].get();
			}
		}
		return ret;
	}

	void clear() { root.reset(); }
	void insert(const value_type &x) {
		::std::size_t i = Bitlength;
		if (!root)
			root = ::std::make_unique<node_type>();
		node_type *ptr = root.get();
		while (++ptr->size, i--) {
			if (!ptr->child[x.test(i) ^ lazy.test(i)])
				ptr->child[x.test(i) ^ lazy.test(i)] = ::std::make_unique<node_type>();
			ptr = ptr->child[x.test(i) ^ lazy.test(i)].get();
		}
	}
	void insert(const value_type &x, const size_type k) {
		::std::size_t i = Bitlength;
		if (!root)
			root = ::std::make_unique<node_type>();
		node_type *ptr = root.get();
		while (ptr->size += k, i--) {
			if (!ptr->child[x.test(i) ^ lazy.test(i)])
				ptr->child[x.test(i) ^ lazy.test(i)] = ::std::make_unique<node_type>();
			ptr = ptr->child[x.test(i) ^ lazy.test(i)].get();
		}
	}
	void erase(const value_type &x) {
		assert(count(x));
		::std::size_t i = Bitlength;
		node_type *ptr = root.get();
		while (--ptr->size, i--)
			ptr = ptr->child[x.test(i) ^ lazy.test(i)].get();
	}
	void erase(const value_type &x, const size_type k) {
		assert(k <= count(x));
		::std::size_t i = Bitlength;
		node_type *ptr = root.get();
		while (ptr->size -= k, i--)
			ptr = ptr->child[x.test(i) ^ lazy.test(i)].get();
	}
	void xor_all(const value_type &x) { lazy ^= x; }
};


#include <cstdio>

int main() {
	using uint = unsigned int;

	uint n, q;
	scanf("%u%u", &n, &q);

	binary_trie<17> s;

	for (uint i = 0;i <= n;++i)
		s.insert(i, 0);

	while (q--) {
		uint com, x, y;
		scanf("%u%u%u", &com, &x, &y);

		if (com) {
			printf("%u\n", s.order_of_key(y) - s.order_of_key(x - 1));
		}
		else {
			s.insert(x - 1, y);
		}

	}
	return 0;
}


Measured memory_bytes: 8920