#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=3e6+5;
const int M=1e7+5;
inline int read()
{
char c=getchar();int num=0;
for(;!isdigit(c);c=getchar());
for(;isdigit(c);c=getchar())
num=num*10+c-'0';
return num;
}
struct QUE
{
int x,y,f,id;
bool operator < (const QUE &A) const
{
return x==A.x?(y==A.y?id<A.id:y<A.y):x<A.x;
}
}tree[N];
int n,m,cnt;
int bound;
int bit[M];
inline void add(int x)
{
for(;x<=bound;x+=x&(-x))
++bit[x];
}
inline int query(int x)
{
int res=0;
for(;x;x-=x&(-x))
res+=bit[x];
return res;
}
int ans[N];
int main()
{
n=read(),m=read();
for(int i=1;i<=n;++i)
{
tree[i].x=read(),++++tree[i].x, //树状数组下标不能从0开始,因为0的二进制上没有1,会死循环,所以让左标++
tree[i].y=read(),++++tree[i].y;
bound=max(bound,tree[i].y);
}
cnt=n;
for(int i=1,a,b,c,d;i<=m;++i)
{
a=read(),b=read(),c=read(),d=read();
++a,++b,++++c,++++d; //a和b不用加,因为二维前缀和要-query(a+1-1)=query(a)
tree[++cnt].x=a,tree[cnt].y=b,tree[cnt].f=1,tree[cnt].id=i; //二维前缀和 左上角
tree[++cnt].x=a,tree[cnt].y=d,tree[cnt].f=-1,tree[cnt].id=i; //左下角
tree[++cnt].x=c,tree[cnt].y=b,tree[cnt].f=-1,tree[cnt].id=i; //右上角
tree[++cnt].x=c,tree[cnt].y=d,tree[cnt].f=1,tree[cnt].id=i; //右下角
}
sort(tree+1,tree+cnt+1);
for(int i=1;i<=cnt;++i)
{
if(!tree[i].id) //插入
add(tree[i].y);
else //查询
ans[tree[i].id]+=query(tree[i].y)*tree[i].f;
}
for(int i=1;i<=m;++i)
printf("%d\n",ans[i]);
return 0;
}