//#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 {
	const Integral f, l;

public:
	using value_type = Integral;
	using reference = value_type;
	class irangeitr {
		friend irange;
		value_type i;
		irangeitr(value_type x) noexcept : i(x) {}

	public:
		void operator++() noexcept { ++i; }
		reference operator*() const noexcept { return i; }
		bool operator!=(const irangeitr &x) const noexcept { return i != x.i; }
	};
	irange(value_type first, 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>(f, l); }
};
template <class Integral = std::size_t> class Rirange {
	const Integral f, l;

public:
	using value_type = Integral;
	using reference = value_type;
	class Rirangeitr {
		friend Rirange;
		value_type i;
		Rirangeitr(value_type x) noexcept : i(x) {}

	public:
		void operator++() noexcept { --i; }
		reference operator*() const noexcept { return i - 1; }
		bool operator!=(const Rirangeitr &x) const noexcept { return i != x.i; }
	};
	Rirange(value_type first, value_type last) noexcept : f(first), l(last) {}
	Rirangeitr begin() const noexcept { return Rirangeitr(l); }
	Rirangeitr end() const noexcept { return Rirangeitr(f); }
	irange<value_type> rev() const noexcept { return irange<value_type>(f, l); }
};

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;
	void get_c() { c = fgetc(stdin); }
	void put_c(int x) { fputc(x, stdout); }
	bool vacant() { return c == ' ' || c == '\n'; }
	operator int() { return 0; }

	// 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 + c - '0';
		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 + c - '0';
		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++] = d % 10 + '0', d /= 10;
		if (!c)
			buf[c++] = '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++] = d % 10 + '0', d /= 10;
		if (!c)
			buf[c++] = '0';
		while (c--)
			put_c(buf[c]);
		return *this;
	}
	customIO &operator<<(char d) {
		put_c(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;
	}
	customIO &operator<<(double d) {
		/*
		printf("%1.9f",d);
		/*/
		printf("%f", 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 <algorithm>
#include <utility>
#include <vector>
#include <algorithm>
#include <array>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <utility>
#include <vector>

template <typename Integral,
	std::size_t bitsize = std::numeric_limits<Integral>::digits()>
	class WaveletMatrix {
	public:
		using value_type = Integral;
		using size_type = std::size_t;

	private:
		using uint32 = std::uint_least32_t;
		static size_type popcount32(uint32 c) {
#ifdef __GNUC__
			return __builtin_popcount(c);
#elif _MSC_VER_
			return _mm_popcnt_u32(c);
#else
			c = (c & 0x55555555) + ((c >> 1) & 0x55555555);
			c = (c & 0x33333333) + ((c >> 2) & 0x33333333);
			c = (c + (c >> 4)) & 0x0F0F0F0F;
			c += c >> 8;
			c += c >> 16;
			return static_cast<size_type>(c) & 0x3F;
#endif
		}
		struct FID {
			std::vector<uint32> dic;
			size_type cnt;
			value_type bit;
			FID() {}
			FID(const size_type bsize) : dic(bsize, 0) {}
			void set(const size_type index) {
				dic[index >> 4 | 1] |= static_cast<uint32>(1) << (index & 0x1f);
			}
			void build() {
				const size_type len = dic.size();
				for (size_type j = 2; j < len; j += 2)
					dic[j] = dic[j - 2] + popcount32(dic[j - 1]);
			}
			size_type rank(const size_type last) const {
				return static_cast<size_type>(
					dic[last >> 4 & ~static_cast<size_type>(1)]) +
					popcount32(dic[last >> 4 | 1] &
					(static_cast<size_type>(1) << (last & 0x1f)) - 1);
			}
			bool access(const size_type index) const {
				return dic[index >> 4 | 1] >> (index & 0x1f) & 1;
			}
		};
		std::array<FID, bitsize> matrix;
		value_type NOT_FOUND;
		size_type size_;

	public:
		WaveletMatrix(std::vector<value_type> data, const value_type NOT_FOUND = 0)
			: size_(data.size()), NOT_FOUND(NOT_FOUND) {
			const size_type len = data.size(), block = ((len >> 5) + 1) << 1;
			std::vector<value_type> L(len), R(len);
			size_type l, r;
			value_type temp = static_cast<value_type>(1) << (bitsize - 1);
			for (auto &x : matrix) {
				x = FID(block);
				x.bit = temp;
				temp = temp >> 1 & ~temp;
				l = 0;
				r = 0;
				for (size_type j = 0; j < len; ++j)
					if (data[j] & x.bit)
						R[r++] = data[j], x.set(j);
					else
						L[l++] = data[j];
				x.cnt = l;
				x.build();
				std::swap(data, L);
				std::copy(R.begin(), R.begin() + r, data.begin() + l);
			}
		}

		size_type size() const noexcept { return size_; }
		bool empty() const noexcept { return size() == 0; }

		value_type access(size_type index) const {
			assert(index < size());
			value_type ret = 0;
			for (const auto &x : matrix)
				if (x.access(index))
					ret |= x.bit, index = x.rank(index) + x.cnt;
				else
					index -= x.rank(index);
			return ret;
		}
		value_type operator[](const size_type index) const {
			assert(index < size());
			return access(index);
		}
		size_type rank(size_type first, size_type last, const value_type data) const {
			assert(first <= size());
			assert(last <= size());
			assert(first <= last);
			for (const auto &x : matrix)
				if (data & x.bit)
					first = x.rank(first) + x.cnt, last = x.rank(last) + x.cnt;
				else
					first -= x.rank(first), last -= x.rank(last);
			return last - first;
		}
		value_type quantile(size_type first, size_type last, size_type k) const {
			assert(first < size());
			assert(last <= size());
			assert(first < last);
			assert(last - first > k);
			value_type ret = 0;
			for (const auto &x : matrix) {
				const size_type l = x.rank(first), r = x.rank(last);
				if (r - l > k)
					first = l + x.cnt, last = r + x.cnt, ret |= x.bit;
				else
					first -= l, last -= r, k -= r - l;
			}
			return ret;
		}
		value_type rquantile(size_type first, size_type last, size_type k) const {
			assert(first < size());
			assert(last <= size());
			assert(first < last);
			assert(last - first > k);
			return quantile(first, last, last - first - k - 1);
		}
		size_type less_than(size_type first, size_type last,
			const value_type data) const {
			assert(first <= size());
			assert(last <= size());
			assert(first <= last);
			size_type ret = 0;
			for (const auto &x : matrix) {
				if (data & x.bit) {
					ret += last - first + x.rank(first) - x.rank(last);
					first = x.rank(first) + x.cnt;
					last = x.rank(last) + x.cnt;
				}
				else {
					first -= x.rank(first);
					last -= x.rank(last);
				}
			}
			return ret;
		}
		size_type at_least(size_type first, size_type last,
			const value_type data) const {
			assert(first <= size());
			assert(last <= size());
			assert(first <= last);
			size_type ret = 0;
			for (const auto &x : matrix) {
				if (data & x.bit) {
					first = x.rank(first) + x.cnt;
					last = x.rank(last) + x.cnt;
				}
				else {
					ret += x.rank(last) - x.rank(first);
					first -= x.rank(first);
					last -= x.rank(last);
				}
			}
			return ret + (last - first);
		}
		size_type greater_than(size_type first, size_type last,
			const value_type data) const {
			assert(first <= size());
			assert(last <= size());
			assert(first <= last);
			size_type ret = 0;
			for (const auto &x : matrix) {
				if (data & x.bit) {
					first = x.rank(first) + x.cnt;
					last = x.rank(last) + x.cnt;
				}
				else {
					ret += x.rank(last) - x.rank(first);
					first -= x.rank(first);
					last -= x.rank(last);
				}
			}
			return ret;
		}
		size_type at_most(size_type first, size_type last,
			const value_type data) const {
			assert(first <= size());
			assert(last <= size());
			assert(first <= last);
			size_type ret = 0;
			for (const auto &x : matrix) {
				if (data & x.bit) {
					ret += last - first + x.rank(first) - x.rank(last);
					first = x.rank(first) + x.cnt;
					last = x.rank(last) + x.cnt;
				}
				else {
					first -= x.rank(first);
					last -= x.rank(last);
				}
			}
			return ret + (last - first);
		}
		size_type rangefreq(size_type first, size_type last, const value_type lower,
			const value_type upper) const {
			assert(first <= size());
			assert(last <= size());
			assert(first <= last);
			assert(lower <= upper);
			return at_least(first, last, lower) - at_least(first, last, upper);
		}
		value_type successor(const size_type first, const size_type last,
			const value_type data) const {
			assert(first <= size());
			assert(last <= size());
			assert(first <= last);
			const size_type k = at_least(first, last, data);
			return k ? quantile(first, last, k - 1) : NOT_FOUND;
		}
		value_type predecessor(const size_type first, const size_type last,
			const value_type data) const {
			assert(first <= size());
			assert(last <= size());
			assert(first <= last);
			const size_type k = greater_than(first, last, data);
			return last - first == k ? NOT_FOUND : quantile(first, last, k);
		}
		value_type strict_succ(const size_type first, const size_type last,
			const value_type data) const {
			assert(first <= size());
			assert(last <= size());
			assert(first <= last);
			const size_type k = greater_than(first, last, data);
			return k ? quantile(first, last, k - 1) : NOT_FOUND;
		}
		value_type strict_pred(const size_type first, const size_type last,
			const value_type data) const {
			assert(first <= size());
			assert(last <= size());
			assert(first <= last);
			const size_type k = at_least(first, last, data);
			return last - first == k ? NOT_FOUND : quantile(first, last, k);
		}
};
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <functional>
#include <iterator>
#include <memory>
#include <utility>
#include <vector>

template <class T>
using StaticSetDefaultContainer = std::vector<T, std::allocator<T>>;

template <class T = std::uint_fast32_t,
	template <class> class Container = StaticSetDefaultContainer,
	class Compare = std::less<typename Container<T>::value_type>>
	class StaticSet {
	public:
		using container_type = Container<T>;
		using value_compare = Compare;
		using value_type = typename container_type::value_type;
		using reference = typename container_type::reference;
		using const_reference = typename container_type::const_reference;
		using size_type = typename container_type::size_type;
		using difference_type = typename container_type::difference_type;
		using pointer = typename container_type::pointer;
		using const_pointer = typename container_type::const_pointer;
		class const_iterator : public std::random_access_iterator_tag {
			friend StaticSet;

		public:
			using difference_type = typename StaticSet::difference_type;
			using value_type = typename StaticSet::value_type;
			using pointer = typename StaticSet::const_pointer;
			using reference = typename StaticSet::const_reference;

		private:
			using iterator_type = typename StaticSet::container_type::const_iterator;
			iterator_type it;
			difference_type ord;
			explicit const_iterator(iterator_type x, difference_type y)
				: it(x), ord(y) {}

		public:
			reference operator*() const { return *it; }
			pointer operator->() const { return std::addressof(operator*()); }
			reference operator[](difference_type n) const { return it[n]; }

			const_iterator &operator++() {
				if (++ord)
					++it;
				return *this;
			}
			const_iterator operator++(int) {
				auto ret = *this;
				operator++();
				return ret;
			}
			const_iterator &operator--() {
				if (ord--)
					--it;
				return *this;
			}
			const_iterator operator--(int) {
				auto ret = *this;
				operator--();
				return ret;
			}
			const_iterator &operator+=(difference_type n) {
				if (ord >= static_cast<difference_type>(0))
					it += n, ord += n;
				else if (n)
					it += n - 1, ord += n;
				return *this;
			}
			const_iterator operator+(difference_type n) const {
				if (ord >= static_cast<difference_type>(0))
					return const_iterator(it + n, ord + n);
				else
					return const_iterator(it + n - 1, ord + n);
			}
			const_iterator &operator-=(difference_type n) {
				it -= n, ord -= n;
				return *this;
			}
			const_iterator operator-(difference_type n) const {
				return const_iterator(it - n, ord - n);
			}

			difference_type operator-(const const_iterator &other) const {
				return ord - other.ord;
			}

			bool operator==(const const_iterator &other) const {
				return it == other.it && ord == other.ord;
			}
			bool operator!=(const const_iterator &other) const {
				return it != other.it || ord != other.ord;
			}
			bool operator<(const const_iterator &other) const {
				return ord < other.ord;
			}
			bool operator<=(const const_iterator &other) const {
				return ord <= other.ord;
			}
			bool operator>(const const_iterator &other) const {
				return ord > other.ord;
			}
			bool operator>=(const const_iterator &other) const {
				return ord >= other.ord;
			}

			reference value() const { return operator*(); }
			difference_type order() const { return ord; }
		};
		using iterator = const_iterator;

	protected:
		container_type c;
		value_compare comp;

	private:
		const_iterator make_citr(typename const_iterator::iterator_type it) const {
			return const_iterator(it, std::distance(c.cbegin(), it));
		}

	public:
		StaticSet() : c(), comp() {}
		explicit StaticSet(const value_compare &x) : comp(x) {}
		explicit StaticSet(const value_compare &x, const container_type &other)
			: c(other), comp(x) {
			build();
		}
		explicit StaticSet(const value_compare &x, container_type &&other)
			: c(std::move(other)), comp(x) {
			build();
		}

		const_iterator cbegin() const { return make_citr(c.cbegin()); }
		const_iterator cend() const { return make_citr(c.cend()); }
		iterator begin() { return cbegin(); }
		iterator end() { return cend(); }

		size_type size() const { return c.size(); }
		bool empty() const { return c.empty(); }
		void reserve(const size_type s) { c.reserve(s); }
		void shrink_to_fit() { c.shrink_to_fit(); }

		const_reference operator[](size_type n) const {
			assert(n < size());
			return c[n];
		}
		const_reference at(size_type n) const { return c.at(n); }
		const_reference min() const {
			assert(!empty());
			return c.front();
		}
		const_reference max() const {
			assert(!empty());
			return c.back();
		}
		const_iterator succ(const value_type &x) const {
			return make_citr(std::lower_bound(c.cbegin(), c.cend(), x, comp));
		}
		const_iterator pred(const value_type &x) const {
			return make_citr(std::upper_bound(c.cbegin(), c.cend(), x, comp) - 1);
		}
		const_iterator strict_succ(const value_type &x) const {
			return make_citr(std::upper_bound(c.cbegin(), c.cend(), x, comp));
		}
		const_iterator strict_pred(const value_type &x) const {
			return make_citr(std::lower_bound(c.cbegin(), c.cend(), x, comp) - 1);
		}

		void push(const value_type &x) { c.push_back(x); }
		void push(value_type &&x) { c.push_back(std::move(x)); }
		template <class... Args> void emplace(Args &&... args) {
			c.emplace_back(std::forward<Args>(args)...);
		}
		void build() { std::sort(c.begin(), c.end(), comp); }
		void unique() { c.erase(std::unique(c.begin(), c.end()), c.end()); }
		void clear() { c.clear(); }
};

int main() {
	constexpr int32 base = 1000000000;
	uint32 n, m;
	IO >> n >> m;
	using P = std::pair<int32, int32>;
	StaticSet<P> s;
	s.reserve(n);
	while (n--) {
		int32 x, y;
		IO >> x >> y;
		y += base;
		s.emplace(x, y);
	}
	s.build();
	std::vector<uint32> a;
	a.reserve(s.size());
	for (const auto &e : s)
		a.emplace_back(e.second);
	WaveletMatrix<uint32, 31> W(a);
	while (m--) {
		int32 a, b, c, d;
		IO >> a >> b >> c >> d;
		++c;
		++d;
		b += base;
		d += base;
		IO << W.rangefreq(s.succ(P(a, 0)).order(), s.succ(P(c, 0)).order(), b, d) << '\n';
	}
	return 0;
}


Measured memory_bytes: 2752