Problem:
宝探し

太郎君はある広場にお宝を探しにやってきました。この広場にはたくさんのお宝が埋められていますが、太郎君は最新の機械を持っているので、どこにお宝が埋まっているかをすべて知っています。広場はとても広いので太郎君は領域を決めてお宝を探すことにしましたが、お宝はたくさんあるためどのお宝がその領域の中にあるかすぐにわかりません。そこで太郎君はその領域の中にあるお宝の数を数えることにしました。

Input

n m
x1 y1
x2 y2
...
xn yn
x11 y11 x12 y12
x21 y21 x22 y22
...
xm1 ym1 xm2 ym2

nは広場に埋まっているお宝の数を表す

mは調べる領域の数を表す

2行目からn+1行目はそれぞれのお宝が埋まっている座標を表す

n+2行目からn+m+1行目はそれぞれの調べる領域を表す

x軸の正の方向が東、y軸の正の方向が北を表す

それぞれの領域は長方形であり、xi1とyi1は長方形の南西の頂点の座標、xi2とyi2は長方形の北東の頂点の座標を表す

Constraints

1 ≤ n ≤ 5000
1 ≤ m ≤ 5×105
|xi|, |yi| ≤ 109 (1 ≤ i ≤ n)
|xi1|, |yi1|, |xi2|, |yi2| ≤ 109 (1 ≤ i ≤ m)
xi1 ≤ xi2, yi1 ≤ yi2 (1 ≤ i ≤ m)

すべての入力は整数で与えられる

Output

C1
C2
...
Cm

それぞれの領域に含まれるお宝の数を各行に出力せよ

Sample Input 1

3 1
1 1
2 4
5 3
0 0 5 5

Output for the Sample Input 1

3

領域の境界線上にあるお宝も領域に含まれるものとみなす

Sample Input 2

4 2
-1 1
0 3
4 0
2 1
-3 1 5 1
4 0 4 0

Output for the Sample Input 2

2
1

領域は直線や点のようになる場合もある

Sample Input 3

2 3
0 0
0 0
-1 -1 1 1
0 0 2 2
1 1 4 4

Output for the Sample Input 3

2
2
0

同じ場所に複数のお宝が存在する場合もある

Sample Input 4

5 5
10 5
-3 -8
2 11
6 0
-1 3
-3 1 3 13
-1 -1 9 5
-3 -8 10 11
0 0 5 5
-10 -9 15 10

Output for the Sample Input 4

2
2
5
0
4

Solution in JAVA (judge verdict: Accepted)

import static java.util.Arrays.binarySearch;

import java.io.IOException;
import java.util.TreeSet;

public class Main {

	public static void main(String[] args) {
		int n = nextInt();
		int m = nextInt();
		int[] xs = new int[n];
		int[] ys = new int[n];
		for (int i = 0; i < n; i++) {
			xs[i] = nextInt();
			ys[i] = nextInt();
		}

		TreeSet<Integer> xSet = new TreeSet<Integer>();
		TreeSet<Integer> ySet = new TreeSet<Integer>();

		for (int i = 0; i < n; i++) {
			xSet.add(xs[i]);
			ySet.add(ys[i]);
		}
		xSet.add((int) Integer.MAX_VALUE);
		xSet.add((int) Integer.MIN_VALUE);
		ySet.add((int) Integer.MAX_VALUE);
		ySet.add((int) Integer.MIN_VALUE);

		Integer[] xss = xSet.toArray(new Integer[0]);
		Integer[] yss = ySet.toArray(new Integer[0]);

		int w = xss.length;
		int h = yss.length;

		int[][] location = new int[h + 1][w + 1];

		for (int i = 0; i < n; i++) {
			int x = binarySearch(xss, xs[i]);
			int y = binarySearch(yss, ys[i]);
			location[y + 1][x + 1]++;
		}

		for (int i = 0; i < w; i++) {
			for (int j = 0; j < h; j++) {
				location[j + 1][i + 1] += location[j + 1][i] + location[j][i + 1] - location[j][i];
			}
		}

		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < m; i++) {
			int x1 = binarySearch(xss, xSet.ceiling(nextInt()));
			int y1 = binarySearch(yss, ySet.ceiling(nextInt()));
			int x2 = binarySearch(xss, xSet.floor(nextInt())) + 1;
			int y2 = binarySearch(yss, ySet.floor(nextInt())) + 1;
			sb.append(location[y2][x2] - location[y1][x2] - location[y2][x1] + location[y1][x1]);
			sb.append('\n');
		}
		System.out.print(sb.toString());
	}

	static int nextInt() {
		int c;
		try {
			c = System.in.read();
			while (c != '-' && (c < '0' || c > '9'))
				c = System.in.read();
			if (c == '-')
				return -nextInt();
			int res = 0;
			while (c >= '0' && c <= '9') {
				res = res * 10 + c - '0';
				c = System.in.read();
			}
			return res;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return -1;
	}

}