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: Time Limit Exceeded)

import java.util.*;
import static java.lang.Math.*;

public class Main {
	final Scanner sc=new Scanner(System.in);
	public static void main(String[] args) {
		new Main().init();
	}
	void init(){
		new AOJ2426();
	}
	
	class AOJ2426{
		AOJ2426(){
			//while(sc.hasNext()){
				int N=sc.nextInt(),M=sc.nextInt();
				//if(N==0 && M==0)	break;
				solve(N,M);
			//}
		}
		void solve(int N,int M){
			//TreeSet<Integer> xs=new TreeSet<Integer>(),ys=new TreeSet<Integer>();
			HashSet<Integer> xs=new HashSet<Integer>(), ys=new HashSet<Integer>();
			int[] x1=new int[N],y1=new int[N];
			for(int i=0; i<N; i++){
				x1[i]=sc.nextInt();
				y1[i]=sc.nextInt();
				xs.add(x1[i]);
				ys.add(y1[i]);
			}
			int[] x2=new int[xs.size()],y2=new int[ys.size()];
			int idx=0;
			for(int i:xs)	x2[idx++]=i;
			idx=0;
			for(int i:ys)	y2[idx++]=i;
			Arrays.sort(x2);
			Arrays.sort(y2);
			int[][] sum=new int[xs.size()][ys.size()];
			for(int i=0; i<N; i++)	++sum[Arrays.binarySearch(x2, x1[i])][Arrays.binarySearch(y2, y1[i])];
			for(int x=1; x<x2.length; x++)	sum[x][0]+=sum[x-1][0];
			for(int y=1; y<y2.length; y++)	sum[0][y]+=sum[0][y-1];
			for(int x=1; x<x2.length; x++)for(int y=1; y<y2.length; y++)	sum[x][y]+=sum[x-1][y]+sum[x][y-1]-sum[x-1][y-1];
			
			// TODO debug
//			System.out.print("   ");
//			for(int x=0; x<xs.size(); x++)System.out.printf("%3d",x2[x]);
//			System.out.println();
//			for(int y=ys.size()-1; y>=0; y--){
//				System.out.printf("%3d",y2[y]);
//				for(int x=0; x<xs.size(); x++)System.out.printf("%3d",sum[x][y]);
//				System.out.println();
//			}
			
			for(int i=0; i<M; i++){
				int xm1=sc.nextInt(),ym1=sc.nextInt(),xm2=sc.nextInt(),ym2=sc.nextInt();
				int tmp=Arrays.binarySearch(x2, xm1);
				int xidx1=(tmp>=0?tmp: abs(tmp)-1);
				tmp=Arrays.binarySearch(y2, ym1);
				int yidx1=(tmp>=0?tmp: abs(tmp)-1);
				tmp=Arrays.binarySearch(x2, xm2);
				int xidx2=(tmp>=0?tmp:min(x2.length-1, abs(tmp)-2));
				tmp=Arrays.binarySearch(y2, ym2);
				int yidx2=(tmp>=0?tmp:min(y2.length-1, abs(tmp)-2));
				//System.out.println(xidx1+","+yidx1+" "+xidx2+","+yidx2);
				System.out.println(sum[xidx2][yidx2]-(xidx1>0?sum[xidx1-1][yidx2]:0)-(yidx1>0?sum[xidx2][yidx1-1]:0)+(xidx1>0&&yidx1>0?sum[xidx1-1][yidx1-1]:0));
			}
		}
	}
	
	class AOJ2429{
		int N;
		int[][] W,E;
		AOJ2429(){
			N=sc.nextInt();
			W=new int[N][N];
			E=new int[N][N];
			for(int y=0; y<N; y++){
				for(int x=0; x<N; x++)	W[x][y]=sc.nextInt();
			}
			for(int y=0; y<N; y++){
				for(int x=0; x<N; x++)	E[x][y]=sc.nextInt();
			}
			StringBuilder init=new StringBuilder();
			int[] w=new int[N],h=new int[N];
			for(int y=0; y<N; y++){
				String str=sc.next();
				for(int x=0; x<N; x++){
					init.append(str);
					if(str.charAt(x)=='o'){
						w[x]++;
						h[y]++;
					}
				}
			}
			
			for(int lim=0; ; lim++){
				State1 res=IDDFS(w.clone(),h.clone(),new StringBuilder(init.toString()),0,0,lim,new ArrayList<State2>(),-1,-1);
				if(res!=null){
					System.out.println(res.cost);
					System.out.println(res.depth);
					for(State2 st2:res.rec)	System.out.println(st2);
				}
			}
		}
		State1 IDDFS(int[] w,int[] h,StringBuilder map,int depth,int cost,int lim,ArrayList<State2> rec,int lx,int ly){
			int nw=0,nh=0;
			for(int i=0; i<N; i++){
				if(w[i]!=1)	nw++;
				if(h[i]!=1)	nh++;
			}
			if(nw==0 && nh==0){
				return new State1(cost,depth,rec);
			}
			int hs=max(nw,nh);
			if(depth+hs>lim)	return null;
			
			//for(int )
			
			return null;
		}
		class State1{
			int cost,depth;
			ArrayList<State2> rec;
			State1(int cost,int depth,ArrayList<State2> rec){
				this.cost=cost;	this.depth=depth;
				this.rec=rec;
			}
		}
		class State2{
			int x,y;
			boolean e;
			State2(int x,int y,boolean e){
				this.x=x;	this.y=y;	this.e=e;
			}
			@Override public String toString(){
				return x+" "+y+(e? " erase": " write");
			}
		}
	}
	
	// JAG SummerCamp2012 Day2#B - A Holiday of Miss Brute Force
	class AOJ2425{
		final int OFFSET=200, MAX=OFFSET*2, INF=Integer.MAX_VALUE/4;
		final int[] vx={0,1,1,0,-1,-1,0},	vy2={1,0,-1,-1,-1,0,0},
											vy1={1,1,0,-1,0,1,0};
		AOJ2425(){
			int sx=sc.nextInt()+OFFSET, sy=sc.nextInt()+OFFSET,
				gx=sc.nextInt()+OFFSET, gy=sc.nextInt()+OFFSET,
				N=sc.nextInt();
			int[] x=new int[N],y=new int[N];
			for(int i=0; i<N; i++){
				x[i]=sc.nextInt()+OFFSET;
				y[i]=sc.nextInt()+OFFSET;
			}
			int LX=sc.nextInt(),LY=sc.nextInt();
			boolean[][] b=new boolean[MAX][MAX];
			for(int i=0; i<N; i++)	b[x[i]][y[i]]=true;
			
			PriorityQueue<State1> open=new PriorityQueue<State1>();
			open.add(new State1(sx,sy,0,0));
			int[][][] close=new int[MAX][MAX][6];
			for(int i=0; i<MAX; i++)for(int j=0; j<MAX; j++)for(int k=0; k<6; k++)close[i][j][k]=INF;
			close[sx][sy][0]=0;
			
			int ans=INF;
			while(!open.isEmpty()){
				State1 now=open.poll();
				//System.out.println(now);
				if(now.x==gx && now.y==gy){
					ans=now.cost;
					break;
				}
				int d=(abs(now.x-OFFSET)*abs(now.y-OFFSET)*now.step)%6;
				for(int i=0; i<7; i++){
					int xx=now.x+vx[i], yy=now.y+(now.x%2==0? vy2[i]: vy1[i]);
					if(abs(xx-OFFSET)>LX || abs(yy-OFFSET)>LY)	continue;
					if(b[xx][yy])	continue;
					int next=now.cost+(d==i? 0: 1);
					if(close[xx][yy][(now.step+1)%6]<=next)	continue;
					open.add(new State1(xx,yy,(now.step+1)%6,next));
					close[xx][yy][(now.step+1)%6]=next;
				}
			}
			System.out.println(ans>=INF? -1: ans);
		}
		class State1 implements Comparable<State1>{
			int x,y,step,cost;
			State1(int x,int y,int step,int cost){
				this.x=x;	this.y=y;	this.step=step;	this.cost=cost;
			}
			@Override public int compareTo(State1 o){
				return (this.cost!=o.cost? this.cost-o.cost: this.step-o.step);
			}
			@Override public String toString(){
				return x+","+y+" "+cost+" "+step+"steps";
			}
		}
	}
}