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 C (judge verdict: Accepted)

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#define N_MAX 5000

int n,m;
int input_map[N_MAX][2];

int za_xnum;
int za_xlist[N_MAX+1];
int za_xlist_raw[N_MAX+1];
int za_ynum;
int za_ylist[N_MAX+1];
int za_ylist_raw[N_MAX+1];
int za_dupe[N_MAX+1];

int treasure_map[N_MAX+5][N_MAX+5];

/* posList[result]<=pos<posList[result+1] */
int za_get(int pos,int isx) {
	int left,right,mid;
	const int* posList;
	left=0;
	if(isx) {
		right=za_xnum-1;
		posList=za_xlist;
	} else {
		right=za_ynum-1;
		posList=za_ylist;
	}
	while(left<=right) {
		mid=(left+right)/2;
		if(posList[mid]==pos)return mid;
		else if(posList[mid]<pos)left=mid+1;
		else right=mid-1;
	}
	return left-1;
}

int qsort_comp(const void* x,const void* y) {
	int a=*((const int*)x);
	int b=*((const int*)y);
	if(a>b)return 1;
	if(a<b)return -1;
	return 0;
}

void za_setup(void) {
	int i;
	za_xlist_raw[n]=INT_MIN;
	za_ylist_raw[n]=INT_MIN;
	qsort(za_xlist_raw,n+1,sizeof(int),qsort_comp);
	qsort(za_ylist_raw,n+1,sizeof(int),qsort_comp);

	za_dupe[0]=0;
	for(i=1;i<=n;i++) {
		if(za_xlist_raw[i]==za_xlist_raw[i-1])za_dupe[i]=1; else za_dupe[i]=0;
		za_dupe[i]+=za_dupe[i-1];
	}
	for(i=0;i<=n;i++)za_xlist[i-za_dupe[i]]=za_xlist_raw[i];
	za_xnum=n+1-za_dupe[n];

	za_dupe[0]=0;
	for(i=1;i<=n;i++) {
		if(za_ylist_raw[i]==za_ylist_raw[i-1])za_dupe[i]=1; else za_dupe[i]=0;
		za_dupe[i]+=za_dupe[i-1];
	}
	for(i=0;i<=n;i++)za_ylist[i-za_dupe[i]]=za_ylist_raw[i];
	za_ynum=n+1-za_dupe[n];
}

int main(void) {
	int i,j;
	scanf("%d%d",&n,&m);
	for(i=0;i<n;i++) {
		scanf("%d%d",&input_map[i][0],&input_map[i][1]);
		za_xlist_raw[i]=input_map[i][0];
		za_ylist_raw[i]=input_map[i][1];
	}
	za_setup();
	for(i=0;i<n;i++) {
		treasure_map[za_get(input_map[i][0],1)][za_get(input_map[i][1],0)]++;
	}
	for(i=0;i<za_xnum;i++) {
		for(j=1;j<za_ynum;j++) {
			treasure_map[i][j]+=treasure_map[i][j-1];
		}
	}
	for(j=0;j<za_ynum;j++) {
		for(i=1;i<za_xnum;i++) {
			treasure_map[i][j]+=treasure_map[i-1][j];
		}
	}

	for(i=0;i<m;i++) {
		int x1,y1,x2,y2;
		int xx1,yy1,xx2,yy2;
		scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
		xx1=za_get(x1,1);
		yy1=za_get(y1,0);
		xx2=za_get(x2,1);
		yy2=za_get(y2,0);
		if(za_xlist[xx1]==x1)xx1--;
		if(za_ylist[yy1]==y1)yy1--;
		printf("%d\n",
			treasure_map[xx2][yy2]-treasure_map[xx1][yy2]-
			treasure_map[xx2][yy1]+treasure_map[xx1][yy1]);
	}

	return 0;
}