Problem:
宝探し
太郎君はある広場にお宝を探しにやってきました。この広場にはたくさんのお宝が埋められていますが、太郎君は最新の機械を持っているので、どこにお宝が埋まっているかをすべて知っています。広場はとても広いので太郎君は領域を決めてお宝を探すことにしましたが、お宝はたくさんあるためどのお宝がその領域の中にあるかすぐにわかりません。そこで太郎君はその領域の中にあるお宝の数を数えることにしました。
Input
n
m
x
1
y
1
x
2
y
2
...
x
n
y
n
x
11
y
11
x
12
y
12
x
21
y
21
x
22
y
22
...
x
m1
y
m1
x
m2
y
m2
n
は広場に埋まっているお宝の数を表す
m
は調べる領域の数を表す
2行目から
n+1
行目はそれぞれのお宝が埋まっている座標を表す
n+2
行目から
n+m+1
行目はそれぞれの調べる領域を表す
x軸の正の方向が東、y軸の正の方向が北を表す
それぞれの領域は長方形であり、
x
i1
と
y
i1
は長方形の南西の頂点の座標、
x
i2
と
y
i2
は長方形の北東の頂点の座標を表す
Constraints
1 ≤ n ≤ 5000
1 ≤ m ≤ 5×10
5
|x
i
|, |y
i
| ≤ 10
9
(1 ≤ i ≤ n)
|x
i1
|, |y
i1
|, |x
i2
|, |y
i2
| ≤ 10
9
(1 ≤ i ≤ m)
x
i1
≤ x
i2
, y
i1
≤ y
i2
(1 ≤ i ≤ m)
すべての入力は整数で与えられる
Output
C
1
C
2
...
C
m
それぞれの領域に含まれるお宝の数を各行に出力せよ
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

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using a2 = array<int, 2>;
using a3 = array<ll, 3>;

bool chmin(auto& a, const auto& b) { return a > b ? a = b, 1 : 0; }
bool chmax(auto& a, const auto& b) { return a < b ? a = b, 1 : 0; }

ll mod = 998244353;
const ll INF = 1e18;

ifstream in;
ofstream out;

int main(int argc, char** argv) {
    ios::sync_with_stdio(false);
    cin.tie(0);

    if(argc > 2) {
        in.open(argv[1]);
        cin.rdbuf(in.rdbuf());
        out.open(argv[2]);
        cout.rdbuf(out.rdbuf());
    }

    ll n, m;
    cin >> n >> m;
    set<int> x, y;
    vector<a2> xy(n);
    for(int i = 0; i < n; i++) {
        int a, b;
        cin >> a >> b;
        xy[i] = {a, b};
        x.insert(a);
        y.insert(b);
    }
    x.insert(-2e9);
    y.insert(-2e9);
    x.insert(2e9);
    y.insert(2e9);

    vector<int> vx(x.begin(), x.end()), vy(y.begin(), y.end());
    map<int, int> mpx, mpy;
    for(int i = 0; i < vx.size(); i++) mpx[vx[i]] = i;
    for(int i = 0; i < vy.size(); i++) mpy[vy[i]] = i;

    vector<vector<int>> sum(vx.size(), vector<int>(vy.size(), 0));
    for(int i = 0; i < n; i++) {
        int xi = mpx[xy[i][0]], yi = mpy[xy[i][1]];
        sum[xi][yi]++;
    }
    for(int i = 1; i < vx.size(); i++) {
        for(int j = 1; j < vy.size(); j++) {
            sum[i][j] += sum[i][j - 1] + sum[i - 1][j] - sum[i - 1][j - 1];
        }
    }
    for(int i = 0; i < m; i++) {
        ll a, b, c, d;
        cin >> a >> b >> c >> d;
        int mnx = lower_bound(vx.begin(), vx.end(), a) - vx.begin() - 1,
            mxx = upper_bound(vx.begin(), vx.end(), c) - vx.begin() - 1;
        int mny = lower_bound(vy.begin(), vy.end(), b) - vy.begin() - 1,
            mxy = upper_bound(vy.begin(), vy.end(), d) - vy.begin() - 1;

        cout << sum[mxx][mxy] - sum[mnx][mxy] - sum[mxx][mny] + sum[mnx][mny]
             << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 480
memory_kb: 102272
final_rank: 11

code_snippet: #include<bits/stdc++.h>
// #include<atcoder/all>
// #include<boost/multiprecision/cpp_int.hpp>

using namespace std;
// using namespace atcoder;
// using bint = boost::multiprecision::cpp_int;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using vi = vector<int>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using ve = vector<vector<int>>;
using vb = vector<bool>;
using vvb = vector<vb>;
#define rep(i,s,n) for(ll i = (ll)s;i < (ll)n;i++)
#define rrep(i,l,r) for(ll i = r-1;i >= l;i--)
#define ALL(x) (x).begin(),(x).end()
#define sz(c) ((ll)(c).size())
#define LB(A,x) (int)(lower_bound(A.begin(),A.end(),x)-A.begin())
#define UB(A,x) (int)(upper_bound(A.begin(),A.end(),x)-A.begin())
// #define MOD 1000000007
#define MOD 998244353
template<typename T>using min_priority_queue=priority_queue<T,vector<T>,greater<T>>;
template<typename T>ostream&operator<<(ostream&os,vector<T>&v){for(int i = 0;i < v.size();i++)os<<v[i]<<(i+1!=v.size()?" ":"");return os;}
template<typename T>istream&operator>>(istream&is,vector<T>&v){for(T&in:v)is>>in;return is;}
template<typename T1,typename T2>ostream&operator<<(ostream&os,pair<T1,T2>&p){os<<p.first<<" "<<p.second;return os;}
template<typename T1,typename T2>istream&operator>>(istream&is,pair<T1,T2>&p){is>>p.first>>p.second;return is;}
template<typename T> inline bool chmax(T &a,T b){if(a < b){a = b;return true;}return false;}
template<typename T> inline bool chmin(T &a,T b){if(a > b){a = b;return true;}return false;}
ld dist(ld x1,ld y1,ld x2, ld y2){return sqrtl((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}


int main(){
  
  ios_base::sync_with_stdio(0), cin.tie(0);
  int n,m;cin >> n >> m;
  vi x(n),y(n);
  vi corX,corY;
  rep(i,0,n)cin >> x[i] >> y[i];
  rep(i,0,n)corX.emplace_back(x[i]),corY.emplace_back(y[i]);
  sort(ALL(corX));corX.erase(unique(ALL(corX)),corX.end());
  sort(ALL(corY));corY.erase(unique(ALL(corY)),corY.end());
  vvi rui(sz(corX)+1,vi(sz(corY)+1));
  rep(i,0,n)rui[LB(corX,x[i])+1][LB(corY,y[i])+1]++;
  rep(i,0,sz(corX))rep(j,0,sz(corY))rui[i+1][j+1] += rui[i][j+1] + rui[i+1][j] - rui[i][j];
  rep(_,0,m){
    ll x,y,X,Y;cin >> x >> y >> X >> Y;
    x = LB(corX,x);y = LB(corY,y);X = LB(corX,X+1);Y = LB(corY,Y+1);
    cout << rui[X][Y]-rui[X][y]-rui[x][Y]+rui[x][y] << "\n";
  }

  

  return 0;
}
accuracy: 1
time_ms: 330
memory_kb: 101012
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
 
using pii = pair<int, int>;
 
int idx(vector<int> const& v, int i) {
    return lower_bound(v.begin(), v.end(), i) - v.begin();
}
 
int main() {
    int n, m;
    cin >> n >> m;
    vector<vector<int>> sum(n + 2, vector<int>(n + 2));
    vector<int> xs(n), ys(n);
    vector<int> x(n), y(n);
    for(int i = 0; i < n; ++i) {
        cin >> x[i] >> y[i];
        xs[i] = x[i];
        ys[i] = y[i];
    }
    sort(x.begin(), x.end());
    x.erase(unique(x.begin(), x.end()), x.end());
    sort(y.begin(), y.end());
    y.erase(unique(y.begin(), y.end()), y.end());
 
    for(int i = 0; i < n; ++i) {
        int tx = idx(x, xs[i]);
        int ty = idx(y, ys[i]);
        ++sum[ty + 1][tx + 1];
    }
    for(int i = 0; i < y.size(); ++i) {
        for(int j = 0; j < x.size(); ++j) {
            sum[i + 1][j + 1] += sum[i + 1][j] + sum[i][j + 1] - sum[i][j];
        }
    }
 
    for(int i = 0; i < m; ++i) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        x1 = idx(x, x1);
        y1 = idx(y, y1);
        x2 = idx(x, x2 + 1);
        y2 = idx(y, y2 + 1);
        cout << sum[y2][x2] - sum[y2][x1] - sum[y1][x2] + sum[y1][x1] << endl;
    }
}
accuracy: 1
time_ms: 1010
memory_kb: 101344
final_rank: 12

code_snippet: #include "bits/stdc++.h"
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;
#define rep(i, m, n) for (ll i = (ll)m; i < (ll)n; i++)
#define drep(i, m, n) for (ll i = m - 1; i >= n; i--)
#define Endl endl
#define all(a) a.begin(), a.end()
#define pr(i, j) make_pair(i, j)
#define isin(x, l, r) (l <= x && x < r)
#define chmin(a, b) a = min(a, b)
#define chmax(a, b) a = max(a, b)
#define srt(ar) sort(ar.begin(), ar.end())
#define rev(ar) reverse(ar.begin(), ar.end())
#define jge(f, s, t) cout << (f ? s : t) << endl
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#define printar(ar)             \
    do                          \
    {                           \
        for (auto dbg : ar)     \
        {                       \
            cout << dbg << " "; \
        }                       \
        cout << endl;           \
    } while (0)
const ll inf = 1e18;
const ld pi = 3.14159265358979;
const ld eps = 1e-9;
template <class T, ll n, ll idx = 0>
auto make_vec(const ll (&d)[n], const T &init) noexcept
{
    if constexpr (idx < n)
        return std::vector(d[idx], make_vec<T, n, idx + 1>(d, init));
    else
        return init;
}

template <class T, ll n>
auto make_vec(const ll (&d)[n]) noexcept
{
    return make_vec(d, T{});
}
//////////////// 以下を貼る ////////////////
template <class T>
size_t HashCombine(const size_t seed, const T &v)
{
    return seed ^ (std::hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
}
/* pair用 */
template <class T, class S>
struct std::hash<std::pair<T, S>>
{
    size_t operator()(const std::pair<T, S> &keyval) const noexcept
    {
        return HashCombine(std::hash<T>()(keyval.first), keyval.second);
    }
};
////////////////////////////////////////////
////////////////////////////////////////////////merge_sort_tree
template <typename T = long long>
class merge_sort_tree
{
private:
    unordered_map<pair<ll, ll>, vector<T>> mp;
    unordered_map<pair<ll, ll>, vector<T>> mp_s;
    vector<T> ar;
    ll sz_ar;
    T INF;
    void init_mp(ll l, ll r)
    {
        vector<T> in;
        vector<ll> in_s(1);
        rep(i, l, r) in.push_back(ar[i]);
        sort(in.begin(), in.end());
        rep(i, 0, r - l) in_s.push_back(in_s.back() + in[i]);
        mp[make_pair(l, r)] = in;
        mp_s[make_pair(l, r)] = in_s;
        if (r - l > 1)
        {
            init_mp(l, (l + r) / 2);
            init_mp((l + r) / 2, r);
        }
    }
    ll cnt_call(ll l, ll r, ll L, ll R, T x)
    {
        if (l <= L && R <= r)
        {
            auto itr = lower_bound(mp[make_pair(L, R)].begin(), mp[make_pair(L, R)].end(), x);
            return distance(mp[make_pair(L, R)].begin(), itr);
        }
        else if (r <= L || R <= l)
            return 0;
        else
            return cnt_call(l, r, L, (L + R) / 2, x) + cnt_call(l, r, (L + R) / 2, R, x);
    }
    ll sum_call(ll l, ll r, ll L, ll R, T x)
    {
        if (l <= L && R <= r)
        {
            auto itr = lower_bound(mp[make_pair(L, R)].begin(), mp[make_pair(L, R)].end(), x);
            return mp_s[make_pair(L, R)][distance(mp[make_pair(L, R)].begin(), itr)];
        }
        else if (r <= L || R <= l)
            return 0;
        else
            return sum_call(l, r, L, (L + R) / 2, x) + sum_call(l, r, (L + R) / 2, R, x);
    }
    T getsup_call(ll l, ll r, ll L, ll R, T x)
    {
        if (l <= L && R <= r)
        {
            auto itr = lower_bound(mp[make_pair(L, R)].begin(), mp[make_pair(L, R)].end(), x);
            if (itr == mp[make_pair(L, R)].begin())
            {
                return -INF;
            }
            return *prev(itr);
        }
        else if (r <= L || R <= l)
            return -INF;
        else
            return max(getsup_call(l, r, L, (L + R) / 2, x), getsup_call(l, r, (L + R) / 2, R, x));
    }
    T getinf_call(ll l, ll r, ll L, ll R, T x)
    {
        if (l <= L && R <= r)
        {
            auto itr = lower_bound(mp[make_pair(L, R)].begin(), mp[make_pair(L, R)].end(), x);
            if (itr == mp[make_pair(L, R)].end())
            {
                return INF;
            }
            return *itr;
        }
        else if (r <= L || R <= l)
            return INF;
        else
            return min(getinf_call(l, r, L, (L + R) / 2, x), getinf_call(l, r, (L + R) / 2, R, x));
    }
    T getmax_call(ll l, ll r, ll L, ll R)
    {
        if (l <= L && R <= r)
        {
            if (mp[make_pair(L, R)].empty())
                return -INF;
            return *(mp[make_pair(L, R)].rbegin());
        }
        else if (r <= L || R <= l)
            return -INF;
        else
            return max(getmax_call(l, r, L, (L + R) / 2), getmax_call(l, r, (L + R) / 2, R));
    }
    T getmin_call(ll l, ll r, ll L, ll R)
    {
        if (l <= L && R <= r)
        {
            if (mp[make_pair(L, R)].empty())
                return INF;
            return *(mp[make_pair(L, R)].begin());
        }
        else if (r <= L || R <= l)
            return INF;
        else
            return min(getmin_call(l, r, L, (L + R) / 2), getmin_call(l, r, (L + R) / 2, R));
    }

public:
    // 初期の配列と、INFとして扱う値で初期化
    merge_sort_tree(vector<T> init, T INF_init)
    {
        sz_ar = 1;
        while (init.size() > sz_ar)
            sz_ar *= 2;
        ar.resize(sz_ar, INF_init);
        INF = INF_init;
        rep(i, 0, init.size())
        {
            ar[i] = init[i];
        }
        init_mp(0, sz_ar);
    }
    //[l,r)においてx未満のものの個数を返す O((logn)^2)
    ll cnt(ll l, ll r, T x)
    {
        return cnt_call(l, r, 0LL, sz_ar, x);
    }
    //[l,r)においてx未満のものの総和を返す O((logn)^2)
    ll sum(ll l, ll r, T x)
    {
        return sum_call(l, r, 0LL, sz_ar, x);
    }
    //[l,r)においてx未満のものの最大値を返す 無ければ-inf O((logn)^2)
    T getsup(ll l, ll r, T x)
    {
        return getsup_call(l, r, 0LL, sz_ar, x);
    }
    //[l,r)においてx以上のものの最小値を返す 無ければinf O((logn)^2)
    T getinf(ll l, ll r, T x)
    {
        return getinf_call(l, r, 0LL, sz_ar, x);
    }
    //[l,r]の最大値を返す O(logn)
    T getmax(ll l, ll r)
    {
        return getmax_call(l, r, 0LL, sz_ar);
    }
    //[l,r]の最小値を返す O(logn)
    T getmin(ll l, ll r)
    {
        return getmin_call(l, r, 0LL, sz_ar);
    }
};

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    ll n, m;
    cin >> n >> m;
    vector<pair<ll, ll>> ar(n);
    rep(i, 0, n)
    {
        cin >> ar[i].first >> ar[i].second;
    }
    srt(ar);
    vector<ll> x, y;
    rep(i, 0, n)
    {
        x.push_back(ar[i].first);
        y.push_back(ar[i].second);
    }
    merge_sort_tree<ll> mst(y,inf);
    rep(i, 0, m)
    {
        ll a, b, c, d;
        cin >> a >> b >> c >> d;
        ll l = distance(x.begin(), lower_bound(all(x), a));
        ll r = distance(x.begin(), upper_bound(all(x), c));
        cout << mst.cnt(l, r, d + 1) - mst.cnt(l, r, b) << endl;
    }
}
accuracy: 1
time_ms: 1110
memory_kb: 8704
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i = 0; i < (n); ++i)
#define repp(i,n) for(int i = 1; i <= (n); ++i)
#define drep(i,n) for(int i = (n)-1; i >= 0; --i)
#define srep(i,s,t) for (int i = s; i < (t); ++i)
#define rng(a) a.begin(),a.end()
#define rrng(a) a.rbegin(),a.rend()
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define em emplace
#define pob pop_back
#define sz(x) (int)(x).size()
#define pcnt __builtin_popcountll
#define koulet srand((unsigned)clock()+(unsigned)time(NULL));
#define newline puts("")
#define vc vector
using namespace std;
template<class T> using vv = vc<vc<T>>;
template<class T> using PQ = priority_queue<T,vc<T>,greater<T>>;
using uint = unsigned; using ull = unsigned long long;
using vi = vc<int>; using vvi = vv<int>; using vvvi = vv<vi>;
using ll = long long; using vl = vc<ll>; using vvl = vv<ll>; using vvvl = vv<vl>;
using P = pair<int,int>; using vp = vc<P>; using vvp = vv<P>; using LP = pair<ll,ll>;
using vs = vc<string>; using vb=vc<bool> ; using vlp = vc<LP> ; 
int geti(){int x;scanf("%d",&x);return x;}
vi pm(int n, int s=0) { vi a(n); iota(rng(a),s); return a;}
template<class T1,class T2>istream& operator>>(istream&i,pair<T1,T2>&v){return i>>v.fi>>v.se;}
template<class T1,class T2>ostream& operator<<(ostream&o,const pair<T1,T2>&v){return o<<v.fi<<","<<v.se;}
template<class T>istream& operator>>(istream&i,vc<T>&v){rep(j,sz(v))i>>v[j];return i;}
template<class T>string join(const T&v,const string&d=""){stringstream s;rep(i,sz(v))(i?s<<d:s)<<v[i];return s.str();}
template<class T>ostream& operator<<(ostream&o,const vc<T>&v){if(sz(v))o<<join(v," ");return o;}
template<class T>void vin(vc<T>&a){int n;cin>>n;a=vc<T>(n);cin>>a;}
template<class T>void vin(vv<T>&a){int n,m;cin>>n>>m;a=vv<T>(n,vc<T>(m));cin>>a;}
template<class T1,class T2>void operator--(pair<T1,T2>&a,int){a.fi--;a.se--;}
template<class T1,class T2>void operator++(pair<T1,T2>&a,int){a.fi++;a.se++;}
template<class T>void operator--(vc<T>&a,int){for(T&x:a)x--;}
template<class T>void operator++(vc<T>&a,int){for(T&x:a)x++;}
template<class T>void operator+=(vc<T>&a,T b){for(T&x:a)x+=b;}
template<class T>void operator-=(vc<T>&a,T b){for(T&x:a)x-=b;}
template<class T>void operator*=(vc<T>&a,T b){for(T&x:a)x*=b;}
template<class T>void operator/=(vc<T>&a,T b){for(T&x:a)x/=b;}
template<class T>void operator+=(vc<T>&a,const vc<T>&b){a.insert(a.end(),rng(b));}
template<class T1,class T2>pair<T1,T2>operator+(const pair<T1,T2>&a,const pair<T1,T2>&b){return {a.fi+b.fi,a.se+b.se};}
template<class T1,class T2>pair<T1,T2>operator-(const pair<T1,T2>&a,const pair<T1,T2>&b){return {a.fi-b.fi,a.se-b.se};}
template<class T>pair<T,T>operator*(const pair<T,T>&a,T b){return {a.fi*b,a.se*b};}
template<class T1,class T2>bool mins(T1& x,const T2&y){if(y<x){x=y;return true;}else return false;}
template<class T1,class T2>bool maxs(T1& x,const T2&y){if(x<y){x=y;return true;}else return false;}
template<class T>T min(const vc<T>&a){return *min_element(rng(a));}
template<class T>T max(const vc<T>&a){return *max_element(rng(a));}
template<class Tx,class Ty>Tx dup(Tx x, Ty y){return (x+y-1)/y;}
template<class T>ll suma(const vc<T>&a){ll s=0;for(auto&&x:a)s+=x;return s;}
template<class T>ll suma(const vv<T>&a){ll s=0;for(auto&&x:a)s+=suma(x);return s;}
template<class T>void uni(T&a){sort(rng(a));a.erase(unique(rng(a)),a.end());}
template<class T>void prepend(vc<T>&a,const T&x){a.insert(a.begin(),x);}
const double eps = 1e-10;
const ll LINF = 1001002003004005006ll;
const int INF = 1001001001;
#define dame { puts("-1"); return 0 ;}
#define yes { puts("Yes"); return 0 ;}
#define no { puts("No"); return 0 ;}
#define rtn(x) { cout<<(x)<<endl;} // flush!
#define yn {puts("Yes");}else{puts("No");}
ll c2(ll n) { return n*(n-1)>>1;}

// Mod int
uint mod = 998244353;//*/
// uint mod = 1000000007;//*/
uint md(ll x) { x%=mod; return x<0?x+mod:x;}
ll md(ll x, ll m) { x%=m; return x<0?x+m:x;}
struct mint {
  uint x;
  mint(): x(0) {}
  mint(ll x):x(md(x)) {}
  mint operator-() const { return mint(0) - *this;}
  mint operator~() const { return mint(1) / *this;}
  mint& operator+=(const mint& a) { if((x+=a.x)>=mod) x-=mod; return *this;}
  mint& operator-=(const mint& a) { if((x+=mod-a.x)>=mod) x-=mod; return *this;}
  mint& operator*=(const mint& a) { x=(ull)x*a.x%mod; return *this;}
  mint& operator/=(const mint& a) { x=(ull)x*a.pow(mod-2).x%mod; return *this;}
  mint operator+(const mint& a) const { return mint(*this) += a;}
  mint operator-(const mint& a) const { return mint(*this) -= a;}
  mint operator*(const mint& a) const { return mint(*this) *= a;}
  mint operator/(const mint& a) const { return mint(*this) /= a;}
  mint pow(ll t) const {
    mint res = 1; for (mint p=x;t;p*=p,t>>=1) if (t&1) res *= p; return res;
  }
  mint ppow(ll t) const { int p=mod-1; return pow((t%p+p)%p);}
  bool operator<(const mint& a) const { return x < a.x;}
  bool operator==(const mint& a) const { return x == a.x;}
  bool operator!=(const mint& a) const { return x != a.x;}
};
mint ex(mint x, ll t) { return x.pow(t);}
istream& operator>>(istream&i,mint&a) {i>>a.x;return i;}
//*
ostream& operator<<(ostream&o,const mint&a) {o<<a.x;return o;}
/*/
ostream& operator<<(ostream&o, const mint&x) {
  int a = x.x, b = 1;
  rep(s,2)rep1(i,1000) {
    int y = ((s?-x:x)*i).x; if (abs(a)+b > y+i) a = s?-y:y, b = i;
  }
  o<<a; if (b != 1) o<<'/'<<b; return o;
}//*/
using vm = vector<mint>;
using vvm = vector<vm>;
struct modinv {
  int n; vm d;
  modinv(): n(2), d({0,1}) {}
  mint operator()(int i) { while (n <= i) d.pb(-d[mod%n]*(mod/n)), ++n; return d[i];}
  mint operator[](int i) const { return d[i];}
} invs;
struct modfact {
  int n; vm d;
  modfact(): n(2), d({1,1}) {}
  mint operator()(int i) { while (n <= i) d.pb(d.back()*n), ++n; return d[i];}
  mint operator[](int i) const { return d[i];}
} facs;
struct modfactinv {
  int n; vm d;
  modfactinv(): n(2), d({1,1}) {}
  mint operator()(int i) { while (n <= i) d.pb(d.back()*invs(n)), ++n; return d[i];}
  mint operator[](int i) const { return d[i];}
} ifacs;
mint comb(int a, int b) {
  if (a < b || b < 0) return 0;
  return facs(a)*ifacs(b)*ifacs(a-b);
}
struct modpow {
  mint x; int n; vm d;
  modpow(mint x=2): x(x), n(1), d(1,1) {}
  mint operator()(int i) { while (n <= i) d.pb(d.back()*x), ++n; return d[i];}
  mint operator[](int i) const { return d[i];}
} two(2);//, owt(invs(2));
//
// Bit Vector (for 64-bit non-negative integer)
struct BitVector {
    // block: bit vector
    // count: the number of 1 within each block
    unsigned int n, zeros;
    vector<unsigned long long> block;
    vector<unsigned int> count;
    
    // constructor
    BitVector() {}
    BitVector(const unsigned int num) {
        resize(num);
    }
    void resize(const unsigned int num) {
        n = num;
        block.assign(((num + 1) >> 6) + 1, 0);
        count.assign(block.size(), 0);
    }
    
    // set val(0 or 1) onto i-th bit, get i-th bit of val(0 or 1)
    void set(const unsigned int i, const unsigned long long val = 1LL) {
        assert((i >> 6) < block.size());
        block[i >> 6] |= (val << (i & 63));
    }
    unsigned int get(const unsigned int i) const {
        assert((i >> 6) < block.size());
        return (const unsigned int)(block[i >> 6] >> (i & 63)) & 1;
    }
    void build() {
        for (unsigned int i = 1; i < block.size(); i++) {
            count[i] = count[i - 1] + __builtin_popcountll(block[i - 1]);
        }
        zeros = rank0(n);
    }
    
    // the number of 1 in [0, i)
    unsigned int rank1(const unsigned int i) const {
        assert((i >> 6) < count.size());
        assert((i >> 6) < block.size());
        return count[i >> 6] +
        __builtin_popcountll(block[i >> 6] & ((1ULL << (i & 63)) - 1ULL));
    }
    // the number of 1 in [i, j)
    unsigned int rank1(const unsigned int i, const unsigned int j) const {
        return rank1(j) - rank1(i);
    }
    // the number of 0 in [0, i)
    unsigned int rank0(const unsigned int i) const {
        return i - rank1(i);
    }
    // the number of 0 in [i, j)
    unsigned int rank0(const unsigned int i, const unsigned int j) const {
        return rank0(j) - rank0(i);
    }
    // the number of 0 in [0, n)
    unsigned int rank0() const {
        return zeros;
    }
};

template<class POS, class VAL> struct BITonWaveletMatrix {
    // inner data
    struct BIT {
        VAL UNITY_SUM = 0;
        int N;
        vector<VAL> dat;
        
        // [0, n)
        BIT() {}
        BIT(int n, VAL unity = 0) : UNITY_SUM(unity), N(n), dat(n, unity) { }
        void init(int n) {
            N = n;
            dat.assign(n, UNITY_SUM);
        }
        
        // a is 0-indexed
        void add(int a, VAL x) {
            for (int i = a; i < (int)dat.size(); i |= i + 1)
                dat[i] = dat[i] + x;
        }
        
        // [0, a), a is 0-indexed
        VAL sum(int a) {
            VAL res = UNITY_SUM;
            for (int i = a - 1; i >= 0; i = (i & (i + 1)) - 1)
                res = res + dat[i];
            return res;
        }
        
        // [a, b), a and b are 0-indexed
        VAL sum(int a, int b) {
            return sum(b) - sum(a);
        }
        
        // debug
        void print() {
            for (int i = 0; i < (int)dat.size(); ++i)
                cout << sum(i, i + 1) << ",";
            cout << endl;
        }
    };
    
    using Point = pair<POS, POS>;
    int n, height;
	POS mi = 0 ;
    vector<BitVector> bv;
    vector<Point> ps;
    vector<POS> ys;
    vector<BIT> bit;

    // constructor (sigma: the number of characters)
    // add_point() cannot be used after build()
    BITonWaveletMatrix() {}
    BITonWaveletMatrix(const vector<Point> &vec) {
        for (auto [x, y] : vec) add_point(x, y);
        build();
    }
    void add_point(POS x, POS y) {
        ps.emplace_back(x, y);
        ys.emplace_back(y);
		mi = min(mi, y) ;
    }
    int xid(POS x) const {
        return lower_bound(ps.begin(), ps.end(), Point(x, mi)) - ps.begin();
    }
    int yid(POS y) const {
        return lower_bound(ys.begin(), ys.end(), y) - ys.begin();
    }
    void build() {
        sort(ps.begin(), ps.end());
        ps.erase(unique(ps.begin(), ps.end()), ps.end());
        n = (int)ps.size();
        sort(ys.begin(), ys.end());
        ys.erase(unique(ys.begin(), ys.end()), ys.end());
        vector<int> v(n), left(n), right(n), ord(n);
        int mv = 1;
        for (int i = 0; i < n; ++i) {
            v[i] = yid(ps[i].second);
            mv = max(mv, v[i]);
        }
        for (height = 1; mv != 0; mv >>= 1) ++height;
        iota(ord.begin(), ord.end(), 0);
        bv.resize(height, BitVector(n));
        bit.assign(height + 1, BIT(n));
        for (int h = height - 1; h >= 0; --h) {
            int l = 0, r = 0;
            for (int i = 0; i < n; ++i) {
                if ((v[ord[i]] >> h) & 1) {
                    bv[h].set(i);
                    right[r++] = ord[i];
                } else {
                    left[l++] = ord[i];
                }
            }
            bv[h].build();
            ord.swap(left);
            for (int i = 0; i < r; ++i) ord[i + l] = right[i];
        }
    }
    
    // add
    void add(const POS x, const POS y, const VAL val) {
        int i = lower_bound(ps.begin(), ps.end(), Point(x, y)) - ps.begin();
        int j = yid(y);
        for (int h = height - 1; h >= 0; --h) {
            int i0 = bv[h].rank0(i);
            if ((j >> h) & 1) {
                i += bv[h].rank0() - i0;
            } else {
                i = i0;
            }
            bit[h].add(i, val);
        }
    }
    
    // sum
    VAL inner_sum(int l, int r, const POS upper) {
        assert(0 <= l && r <= n);
        VAL res = 0;
        for (int h = height - 1; h >= 0; --h) {
            int l0 = bv[h].rank0(l), r0 = bv[h].rank0(r);
            if ((upper >> h) & 1) {
                l += bv[h].rank0() - l0;
                r += bv[h].rank0() - r0;
                res += bit[h].sum(l0, r0);
            } else {
                l = l0;
                r = r0;
            }
        }
        return res;
    }

	// sum [lx, rx)×[ly, ry)
    VAL sum(const POS lx, const POS rx, const POS ly, const POS ry) {
        int l = xid(lx), r = xid(rx);
        return inner_sum(l, r, yid(ry)) - inner_sum(l, r, yid(ly));
    }
};


int main() {
	BITonWaveletMatrix<long long, long long> wm;
	int n, m;cin>>n>>m ;
	vl x(n) , y(n) ;
	rep(i, n){
		cin>>x[i] >>y[i] ;
		wm.add_point(x[i], y[i]) ;
	}
    wm.build();
	
	rep(i, n) wm.add(x[i],y[i],1);
	while(m--){
		ll lx,ly,rx,ry ;cin>>lx>>ly>>rx>>ry;
		cout << wm.sum(lx,rx+1,ly,ry+1) <<endl;
	}


}
accuracy: 1
time_ms: 1190
memory_kb: 4180
final_rank: 6

code_snippet: // competitive-verifier: PROBLEM
#include <iostream>
#include <utility>
#include <vector>
#include <algorithm>
#include <iterator>
/**
 * @brief 座標圧縮
 *
 * @tparam T 要素の型
 */
template <class T>
struct coordinate_compression {
    coordinate_compression() = default;
    coordinate_compression(const std::vector<T> &_data) : data(_data) { build(); }
    const T &operator[](int i) const { return data[i]; }
    void add(T x) { data.emplace_back(x); }
    void build() {
        std::sort(data.begin(), data.end());
        data.erase(std::unique(data.begin(), data.end()), data.end());
    }
    bool exists(T x) const {
        auto it = std::lower_bound(data.begin(), data.end(), x);
        return it != data.end() && *it == x;
    }
    int get(T x) const {
        auto it = std::lower_bound(data.begin(), data.end(), x);
        return std::distance(data.begin(), it);
    }
    int size() const { return data.size(); }
  private:
    std::vector<T> data;
};
/**
 * @brief 座標圧縮
 *
 * @tparam T 要素の型
 * @param v 配列
 * @return std::vector<T>
 */
template <class T>
std::vector<int> compress(const std::vector<T> &v) {
    coordinate_compression cps(v);
    std::vector<int> res;
    res.reserve(std::size(v));
    for (auto &&x : v) res.emplace_back(cps.get(x));
    return res;
}
#include <cassert>
template <class T>
struct cumulative_sum_2d {
    cumulative_sum_2d(int _n, int _m) : v(_n, std::vector<T>(_m)), n(_n), m(_m) {}
    cumulative_sum_2d(const std::vector<std::vector<T>> &_v) : v(_v) { build(); }
    void set(int x, int y, T val) { v[x][y] = val; }
    void add(int x, int y, T val) { v[x][y] += val; }
    void build() {
        n = v.size();
        assert(n > 0);
        m = v[0].size();
        assert(m > 0);
        v.resize(n + 1);
        for (int i = 0; i <= n; ++i) v[i].resize(m + 1);
        for (int i = n - 1; i >= 0; --i) {
            for (int j = m - 1; j >= 0; --j) v[i][j] += v[i][j + 1];
        }
        for (int i = n - 1; i >= 0; --i) {
            for (int j = m - 1; j >= 0; --j) v[i][j] += v[i + 1][j];
        }
    }
    T get(int x1, int y1, int x2, int y2) {
        assert(0 <= x1 && x1 <= x2 && x2 <= n && 0 <= y1 && y1 <= y2 && y2 <= m);
        return v[x1][y1] - v[x1][y2] - v[x2][y1] + v[x2][y2];
    }
  private:
    std::vector<std::vector<T>> v;
    int n, m;
};
int main(void) {
    int n, m;
    std::cin >> n >> m;
    std::vector<std::pair<int, int>> a(n);
    for (int i = 0; i < n; ++i) std::cin >> a[i].first >> a[i].second;
    coordinate_compression<int> cps_x, cps_y;
    for (int i = 0; i < n; ++i) cps_x.add(a[i].first), cps_y.add(a[i].second);
    cps_x.build(), cps_y.build();
    cumulative_sum_2d<int> cs(cps_x.size(), cps_y.size());
    for (int i = 0; i < n; ++i) cs.add(cps_x.get(a[i].first), cps_y.get(a[i].second), 1);
    cs.build();
    for (int i = 0; i < m; ++i) {
        int x1, y1, x2, y2;
        std::cin >> x1 >> y1 >> x2 >> y2;
        std::cout << cs.get(cps_x.get(x1), cps_y.get(y1), cps_x.get(x2 + 1), cps_y.get(y2 + 1))
                  << '\n';
    }
    return 0;
}
accuracy: 1
time_ms: 770
memory_kb: 160256
final_rank: 18

code_snippet: // competitive-verifier: PROBLEM
#include <algorithm>
#include <iterator>
#include <vector>
/**
 * @brief 座標圧縮
 *
 * @tparam T 要素の型
 */
template <class T>
struct coordinate_compression {
    coordinate_compression() = default;
    coordinate_compression(const std::vector<T> &_data) : data(_data) { build(); }
    const T &operator[](int i) const { return data[i]; }
    void add(T x) { data.emplace_back(x); }
    void build() {
        std::sort(data.begin(), data.end());
        data.erase(std::unique(data.begin(), data.end()), data.end());
    }
    bool exists(T x) const {
        auto it = std::lower_bound(data.begin(), data.end(), x);
        return it != data.end() && *it == x;
    }
    int get(T x) const {
        auto it = std::lower_bound(data.begin(), data.end(), x);
        return std::distance(data.begin(), it);
    }
    int size() const { return data.size(); }
  private:
    std::vector<T> data;
};
/**
 * @brief 座標圧縮
 *
 * @tparam T 要素の型
 * @param v 配列
 * @return std::vector<T>
 */
template <class T>
std::vector<int> compress(const std::vector<T> &v) {
    coordinate_compression cps(v);
    std::vector<int> res;
    res.reserve(std::size(v));
    for (auto &&x : v) res.emplace_back(cps.get(x));
    return res;
}
#include <cassert>
template <class T>
struct cumulative_sum_2d {
    cumulative_sum_2d(int _n, int _m) : v(_n, std::vector<T>(_m)), n(_n), m(_m) {}
    cumulative_sum_2d(const std::vector<std::vector<T>> &_v) : v(_v) { build(); }
    void set(int x, int y, T val) { v[x][y] = val; }
    void add(int x, int y, T val) { v[x][y] += val; }
    void build() {
        n = v.size();
        assert(n > 0);
        m = v[0].size();
        assert(m > 0);
        v.resize(n + 1);
        for (int i = 0; i <= n; ++i) v[i].resize(m + 1);
        for (int i = n - 1; i >= 0; --i) {
            for (int j = m - 1; j >= 0; --j) v[i][j] += v[i][j + 1];
        }
        for (int i = n - 1; i >= 0; --i) {
            for (int j = m - 1; j >= 0; --j) v[i][j] += v[i + 1][j];
        }
    }
    T get(int x1, int y1, int x2, int y2) {
        assert(0 <= x1 && x1 <= x2 && x2 <= n && 0 <= y1 && y1 <= y2 && y2 <= m);
        return v[x1][y1] - v[x1][y2] - v[x2][y1] + v[x2][y2];
    }
  private:
    std::vector<std::vector<T>> v;
    int n, m;
};
#ifdef ATCODER
#pragma GCC target("sse4.2,avx512f,avx512dq,avx512ifma,avx512cd,avx512bw,avx512vl,bmi2")
#endif
#pragma GCC optimize("Ofast,fast-math,unroll-all-loops")
#include <bits/stdc++.h>
#ifndef ATCODER
#pragma GCC target("sse4.2,avx2,bmi2")
#endif
template <class T, class U>
constexpr bool chmax(T &a, const U &b) {
    return a < (T)b ? a = (T)b, true : false;
}
template <class T, class U>
constexpr bool chmin(T &a, const U &b) {
    return (T)b < a ? a = (T)b, true : false;
}
constexpr std::int64_t INF = 1000000000000000003;
constexpr int Inf = 1000000003;
constexpr double EPS = 1e-7;
constexpr double PI = 3.14159265358979323846;
#define FOR(i, m, n) for (int i = (m); i < int(n); ++i)
#define FORR(i, m, n) for (int i = (m)-1; i >= int(n); --i)
#define FORL(i, m, n) for (int64_t i = (m); i < int64_t(n); ++i)
#define rep(i, n) FOR (i, 0, n)
#define repn(i, n) FOR (i, 1, n + 1)
#define repr(i, n) FORR (i, n, 0)
#define repnr(i, n) FORR (i, n + 1, 1)
#define all(s) (s).begin(), (s).end()
struct Sonic {
    Sonic() {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        std::cout << std::fixed << std::setprecision(20);
    }
    constexpr void operator()() const {}
} sonic;
using namespace std;
using ll = std::int64_t;
using ld = long double;
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
    return is >> p.first >> p.second;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
    for (T &i : v) is >> i;
    return is;
}
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
    return os << '(' << p.first << ',' << p.second << ')';
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {
    for (auto it = v.begin(); it != v.end(); ++it) os << (it == v.begin() ? "" : " ") << *it;
    return os;
}
template <class Head, class... Tail>
void co(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cout << head << '\n';
    else std::cout << head << ' ', co(std::forward<Tail>(tail)...);
}
template <class Head, class... Tail>
void ce(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cerr << head << '\n';
    else std::cerr << head << ' ', ce(std::forward<Tail>(tail)...);
}
void Yes(bool is_correct = true) { std::cout << (is_correct ? "Yes\n" : "No\n"); }
void No(bool is_not_correct = true) { Yes(!is_not_correct); }
void YES(bool is_correct = true) { std::cout << (is_correct ? "YES\n" : "NO\n"); }
void NO(bool is_not_correct = true) { YES(!is_not_correct); }
void Takahashi(bool is_correct = true) { std::cout << (is_correct ? "Takahashi" : "Aoki") << '\n'; }
void Aoki(bool is_not_correct = true) { Takahashi(!is_not_correct); }
int main(void) {
    int n, m;
    cin >> n >> m;
    std::vector<std::pair<int, int>> a(n);
    for (int i = 0; i < n; ++i) std::cin >> a[i].first >> a[i].second;
    coordinate_compression<int> cps_x, cps_y;
    for (int i = 0; i < n; ++i) cps_x.add(a[i].first), cps_y.add(a[i].second);
    cps_x.build(), cps_y.build();
    cumulative_sum_2d<int> cs(cps_x.size(), cps_y.size());
    for (int i = 0; i < n; ++i) cs.add(cps_x.get(a[i].first), cps_y.get(a[i].second), 1);
    cs.build();
    for (int i = 0; i < m; ++i) {
        int x1, y1, x2, y2;
        std::cin >> x1 >> y1 >> x2 >> y2;
        std::cout << cs.get(cps_x.get(x1), cps_y.get(y1), cps_x.get(x2 + 1), cps_y.get(y2 + 1))
                  << '\n';
    }
    return 0;
}
accuracy: 1
time_ms: 330
memory_kb: 160256
final_rank: 16

code_snippet: // competitive-verifier: PROBLEM https://onlinejudge.u-aizu.ac.jp/problems/2426
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <utility>
#include <cassert>
namespace internal {
// @return same with std::bit::bit_ceil
unsigned int bit_ceil(unsigned int n) {
    unsigned int x = 1;
    while (x < (unsigned int)(n)) x *= 2;
    return x;
}
// @param n `1 <= n`
// @return same with std::bit::countl_zero
int countl_zero(unsigned int n) { return __builtin_clz(n); }
// @param n `1 <= n`
// @return same with std::bit::countr_zero
int countr_zero(unsigned int n) { return __builtin_ctz(n); }
// @param n `1 <= n`
// @return same with std::bit::countr_zero
constexpr int countr_zero_constexpr(unsigned int n) {
    int x = 0;
    while (!(n & (1 << x))) x++;
    return x;
}
}  // namespace internal
#include <limits>
#include <numeric>
template <class T>
struct Add {
    using value_type = T;
    static constexpr T id() { return T(); }
    static constexpr T op(const T &lhs, const T &rhs) { return lhs + rhs; }
    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs + rhs;
    }
};
template <class T>
struct Mul {
    using value_type = T;
    static constexpr T id() { return T(1); }
    static constexpr T op(const T &lhs, const T &rhs) { return lhs * rhs; }
    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs * rhs;
    }
};
template <class T>
struct And {
    using value_type = T;
    static constexpr T id() { return std::numeric_limits<T>::max(); }
    static constexpr T op(const T &lhs, const T &rhs) { return lhs & rhs; }
    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs & rhs;
    }
};
template <class T>
struct Or {
    using value_type = T;
    static constexpr T id() { return T(); }
    static constexpr T op(const T &lhs, const T &rhs) { return lhs | rhs; }
    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs | rhs;
    }
};
template <class T>
struct Xor {
    using value_type = T;
    static constexpr T id() { return T(); }
    static constexpr T op(const T &lhs, const T &rhs) { return lhs ^ rhs; }
    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs ^ rhs;
    }
};
template <class T>
struct Min {
    using value_type = T;
    static constexpr T id() { return std::numeric_limits<T>::max(); }
    static constexpr T op(const T &lhs, const T &rhs) { return std::min(lhs, rhs); }
    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return std::min((U)lhs, rhs);
    }
};
template <class T>
struct Max {
    using value_type = T;
    static constexpr T id() { return std::numeric_limits<T>::lowest(); }
    static constexpr T op(const T &lhs, const T &rhs) { return std::max(lhs, rhs); }
    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return std::max((U)lhs, rhs);
    }
};
template <class T>
struct Gcd {
    using value_type = T;
    static constexpr T id() { return std::numeric_limits<T>::max(); }
    static constexpr T op(const T &lhs, const T &rhs) {
        return lhs == Gcd::id() ? rhs : (rhs == Gcd::id() ? lhs : std::gcd(lhs, rhs));
    }
};
template <class T>
struct Lcm {
    using value_type = T;
    static constexpr T id() { return std::numeric_limits<T>::max(); }
    static constexpr T op(const T &lhs, const T &rhs) {
        return lhs == Lcm::id() ? rhs : (rhs == Lcm::id() ? lhs : std::lcm(lhs, rhs));
    }
};
template <class T>
struct Update {
    using value_type = T;
    static constexpr T id() { return std::numeric_limits<T>::max(); }
    static constexpr T op(const T &lhs, const T &rhs) { return lhs == Update::id() ? rhs : lhs; }
    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs == Update::id() ? rhs : lhs;
    }
};
template <class T>
struct Affine {
    using P = std::pair<T, T>;
    using value_type = P;
    static constexpr P id() { return P(1, 0); }
    static constexpr P op(P lhs, P rhs) {
        return {lhs.first * rhs.first, lhs.first * rhs.second + lhs.second};
    }
};
template <class M>
struct Rev {
    using T = typename M::value_type;
    using value_type = T;
    static constexpr T id() { return M::id(); }
    static constexpr T op(T lhs, T rhs) { return M::op(rhs, lhs); }
};
/**
 * @brief セグメント木
 * @see https://noshi91.hatenablog.com/entry/2020/04/22/212649
 *
 * @tparam M モノイド
 */
template <class M>
struct segment_tree {
  private:
    using T = typename M::value_type;
    struct _segment_tree_reference {
      private:
        segment_tree<M> &self;
        int k;
      public:
        _segment_tree_reference(segment_tree<M> &self, int k) : self(self), k(k) {}
        _segment_tree_reference &operator=(const T &x) {
            self.set(k, x);
            return *this;
        }
        _segment_tree_reference &operator=(T &&x) {
            self.set(k, std::move(x));
            return *this;
        }
        operator T() const { return self.get(k); }
    };
  public:
    segment_tree() : segment_tree(0) {}
    explicit segment_tree(int n, T e = M::id()) : segment_tree(std::vector<T>(n, e)) {}
    template <class U>
    explicit segment_tree(const std::vector<U> &v) : _n(v.size()) {
        _size = internal::bit_ceil(_n);
        _log = internal::countr_zero(_size);
        data = std::vector<T>(_size << 1, M::id());
        for (int i = 0; i < _n; ++i) data[_size + i] = T(v[i]);
        for (int i = _size - 1; i >= 1; --i) update(i);
    }
    const T &operator[](int k) const { return data[k + _size]; }
    _segment_tree_reference operator[](int k) { return _segment_tree_reference(*this, k); }
    T at(int k) const { return data[k + _size]; }
    T get(int k) const { return data[k + _size]; }
    void set(int k, T val) {
        assert(0 <= k && k < _n);
        k += _size;
        data[k] = val;
        for (int i = 1; i <= _log; ++i) update(k >> i);
    }
    void reset(int k) { set(k, M::id()); }
    T all_prod() const { return data[1]; }
    T prod(int a, int b) const {
        assert(0 <= a && b <= _n);
        T l = M::id(), r = M::id();
        for (a += _size, b += _size; a < b; a >>= 1, b >>= 1) {
            if (a & 1) l = M::op(l, data[a++]);
            if (b & 1) r = M::op(data[--b], r);
        }
        return M::op(l, r);
    }
    template <class F>
    int max_right(F f) const {
        return max_right(0, f);
    }
    template <class F>
    int max_right(int l, F f) const {
        assert(0 <= l && l <= _n);
        assert(f(M::id()));
        if (l == _n) return _n;
        l += _size;
        T sm = M::id();
        do {
            while (l % 2 == 0) l >>= 1;
            if (!f(M::op(sm, data[l]))) {
                while (l < _size) {
                    l = (2 * l);
                    if (f(M::op(sm, data[l]))) {
                        sm = M::op(sm, data[l]);
                        l++;
                    }
                }
                return l - _size;
            }
            sm = M::op(sm, data[l]);
            l++;
        } while ((l & -l) != l);
        return _n;
    }
    template <class F>
    int min_left(F f) const {
        return min_left(_n, f);
    }
    template <class F>
    int min_left(int r, F f) const {
        assert(0 <= r && r <= _n);
        assert(f(M::id()));
        if (r == 0) return 0;
        r += _size;
        T sm = M::id();
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!f(M::op(data[r], sm))) {
                while (r < _size) {
                    r = (2 * r + 1);
                    if (f(M::op(data[r], sm))) {
                        sm = M::op(data[r], sm);
                        r--;
                    }
                }
                return r + 1 - _size;
            }
            sm = M::op(data[r], sm);
        } while ((r & -r) != r);
        return 0;
    }
  private:
    int _n, _size, _log;
    std::vector<T> data;
    void update(int k) { data[k] = M::op(data[2 * k], data[2 * k + 1]); }
};
/**
 * @brief 領域木
 *
 * @tparam M
 * @tparam T
 *
 * @see https://hitonanode.github.io/cplib-cpp/segmenttree/rangetree.hpp.html
 */
template <class M, class T = int>
struct range_tree {
  private:
    using Pt = std::pair<T, T>;
    using value_type = typename M::value_type;
  public:
    range_tree() = default;
    void add(T x, T y) noexcept { _pts.emplace_back(x, y); }
    void build() {
        std::sort(_pts.begin(), _pts.end());
        _pts.erase(std::unique(_pts.begin(), _pts.end()), _pts.end());
        _size = _pts.size();
        _range2yxs.resize(_size * 2);
        for (int i = 0; i < _size; i++) _range2yxs[_size + i] = {{_pts[i].second, _pts[i].first}};
        for (int i = _size - 1; i > 0; i--) {
            auto &lch = _range2yxs[i * 2];
            auto &rch = _range2yxs[i * 2 + 1];
            std::merge(lch.begin(), lch.end(), rch.begin(), rch.end(),
                       std::back_inserter(_range2yxs[i]));
            _range2yxs[i].erase(std::unique(_range2yxs[i].begin(), _range2yxs[i].end()),
                                _range2yxs[i].end());
        }
        for (const auto &v : _range2yxs) segtrees.emplace_back(v.size());
    }
    void set(T x, T y, value_type val) {
        int i = std::distance(_pts.begin(), std::lower_bound(_pts.begin(), _pts.end(), Pt{x, y}));
        assert(i < _size && _pts[i] == std::make_pair(x, y));
        for (i += _size; i; i >>= 1) set(i, {x, y}, val);
    }
    value_type prod(T xl, T yl, T xr, T yr) const {
        auto comp = [](const Pt &l, const Pt &r) { return l.first < r.first; };
        int l = _size + std::distance(_pts.begin(),
                                      std::lower_bound(_pts.begin(), _pts.end(), Pt{xl, yr}, comp));
        int r = _size + std::distance(_pts.begin(),
                                      std::lower_bound(_pts.begin(), _pts.end(), Pt{xr, yr}, comp));
        value_type res = M::id();
        while (l < r) {
            if (l & 1) res = M::op(res, prod(l++, yl, yr));
            if (r & 1) res = M::op(res, prod(--r, yl, yr));
            l >>= 1, r >>= 1;
        }
        return res;
    }
    value_type get(T x, T y) const {
        int i = std::distance(_pts.begin(), std::lower_bound(_pts.begin(), _pts.end(), Pt{x, y}));
        return i < _size && _pts[i] == std::make_pair(x, y) ? segtrees[_size + i].get(0) : M::id();
    }
  private:
    int _size;
    std::vector<Pt> _pts;
    std::vector<std::vector<Pt>> _range2yxs;
    std::vector<segment_tree<M>> segtrees;
    void set(int v, Pt p, value_type val) {
        auto i = std::distance(
            _range2yxs[v].begin(),
            std::lower_bound(_range2yxs[v].begin(), _range2yxs[v].end(), Pt{p.second, p.first}));
        segtrees[v].set(i, val);
    }
    value_type prod(int v, T yl, T yr) const {
        auto comp = [&](const Pt &l, const Pt &r) { return l.first < r.first; };
        auto il = std::distance(
            _range2yxs[v].begin(),
            std::lower_bound(_range2yxs[v].begin(), _range2yxs[v].end(), Pt{yl, yl}, comp));
        auto ir = std::distance(
            _range2yxs[v].begin(),
            std::lower_bound(_range2yxs[v].begin(), _range2yxs[v].end(), Pt{yr, yr}, comp));
        return segtrees[v].prod(il, ir);
    }
};
int main(void) {
    int n, m;
    std::cin >> n >> m;
    std::vector<int> x(n), y(n);
    for (int i = 0; i < n; ++i) std::cin >> x[i] >> y[i];
    range_tree<Add<int>> rt;
    for (int i = 0; i < n; ++i) rt.add(x[i], y[i]);
    rt.build();
    for (int i = 0; i < n; ++i) rt.set(x[i], y[i], rt.get(x[i], y[i]) + 1);
    for (int i = 0; i < m; ++i) {
        int a, b, c, d;
        std::cin >> a >> b >> c >> d;
        std::cout << rt.prod(a, b, c + 1, d + 1) << '\n';
    }
    return 0;
}
accuracy: 1
time_ms: 1300
memory_kb: 5492
final_rank: 8

code_snippet: // competitive-verifier: PROBLEM https://onlinejudge.u-aizu.ac.jp/problems/2426
#include <algorithm>
#include <iterator>
#include <utility>
#include <cassert>
#include <vector>
namespace internal {
// @return same with std::bit::bit_ceil
unsigned int bit_ceil(unsigned int n) {
    unsigned int x = 1;
    while (x < (unsigned int)(n)) x *= 2;
    return x;
}
// @param n `1 <= n`
// @return same with std::bit::countl_zero
int countl_zero(unsigned int n) { return __builtin_clz(n); }
// @param n `1 <= n`
// @return same with std::bit::countr_zero
int countr_zero(unsigned int n) { return __builtin_ctz(n); }
// @param n `1 <= n`
// @return same with std::bit::countr_zero
constexpr int countr_zero_constexpr(unsigned int n) {
    int x = 0;
    while (!(n & (1 << x))) x++;
    return x;
}
}  // namespace internal
#include <limits>
#include <numeric>
template <class T>
struct Add {
    using value_type = T;
    static constexpr T id() { return T(); }
    static constexpr T op(const T &lhs, const T &rhs) { return lhs + rhs; }
    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs + rhs;
    }
};
template <class T>
struct Mul {
    using value_type = T;
    static constexpr T id() { return T(1); }
    static constexpr T op(const T &lhs, const T &rhs) { return lhs * rhs; }
    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs * rhs;
    }
};
template <class T>
struct And {
    using value_type = T;
    static constexpr T id() { return std::numeric_limits<T>::max(); }
    static constexpr T op(const T &lhs, const T &rhs) { return lhs & rhs; }
    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs & rhs;
    }
};
template <class T>
struct Or {
    using value_type = T;
    static constexpr T id() { return T(); }
    static constexpr T op(const T &lhs, const T &rhs) { return lhs | rhs; }
    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs | rhs;
    }
};
template <class T>
struct Xor {
    using value_type = T;
    static constexpr T id() { return T(); }
    static constexpr T op(const T &lhs, const T &rhs) { return lhs ^ rhs; }
    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs ^ rhs;
    }
};
template <class T>
struct Min {
    using value_type = T;
    static constexpr T id() { return std::numeric_limits<T>::max(); }
    static constexpr T op(const T &lhs, const T &rhs) { return std::min(lhs, rhs); }
    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return std::min((U)lhs, rhs);
    }
};
template <class T>
struct Max {
    using value_type = T;
    static constexpr T id() { return std::numeric_limits<T>::lowest(); }
    static constexpr T op(const T &lhs, const T &rhs) { return std::max(lhs, rhs); }
    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return std::max((U)lhs, rhs);
    }
};
template <class T>
struct Gcd {
    using value_type = T;
    static constexpr T id() { return std::numeric_limits<T>::max(); }
    static constexpr T op(const T &lhs, const T &rhs) {
        return lhs == Gcd::id() ? rhs : (rhs == Gcd::id() ? lhs : std::gcd(lhs, rhs));
    }
};
template <class T>
struct Lcm {
    using value_type = T;
    static constexpr T id() { return std::numeric_limits<T>::max(); }
    static constexpr T op(const T &lhs, const T &rhs) {
        return lhs == Lcm::id() ? rhs : (rhs == Lcm::id() ? lhs : std::lcm(lhs, rhs));
    }
};
template <class T>
struct Update {
    using value_type = T;
    static constexpr T id() { return std::numeric_limits<T>::max(); }
    static constexpr T op(const T &lhs, const T &rhs) { return lhs == Update::id() ? rhs : lhs; }
    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs == Update::id() ? rhs : lhs;
    }
};
template <class T>
struct Affine {
    using P = std::pair<T, T>;
    using value_type = P;
    static constexpr P id() { return P(1, 0); }
    static constexpr P op(P lhs, P rhs) {
        return {lhs.first * rhs.first, lhs.first * rhs.second + lhs.second};
    }
};
template <class M>
struct Rev {
    using T = typename M::value_type;
    using value_type = T;
    static constexpr T id() { return M::id(); }
    static constexpr T op(T lhs, T rhs) { return M::op(rhs, lhs); }
};
/**
 * @brief セグメント木
 * @see https://noshi91.hatenablog.com/entry/2020/04/22/212649
 *
 * @tparam M モノイド
 */
template <class M>
struct segment_tree {
  private:
    using T = typename M::value_type;
    struct _segment_tree_reference {
      private:
        segment_tree<M> &self;
        int k;
      public:
        _segment_tree_reference(segment_tree<M> &self, int k) : self(self), k(k) {}
        _segment_tree_reference &operator=(const T &x) {
            self.set(k, x);
            return *this;
        }
        _segment_tree_reference &operator=(T &&x) {
            self.set(k, std::move(x));
            return *this;
        }
        operator T() const { return self.get(k); }
    };
  public:
    segment_tree() : segment_tree(0) {}
    explicit segment_tree(int n, T e = M::id()) : segment_tree(std::vector<T>(n, e)) {}
    template <class U>
    explicit segment_tree(const std::vector<U> &v) : _n(v.size()) {
        _size = internal::bit_ceil(_n);
        _log = internal::countr_zero(_size);
        data = std::vector<T>(_size << 1, M::id());
        for (int i = 0; i < _n; ++i) data[_size + i] = T(v[i]);
        for (int i = _size - 1; i >= 1; --i) update(i);
    }
    const T &operator[](int k) const { return data[k + _size]; }
    _segment_tree_reference operator[](int k) { return _segment_tree_reference(*this, k); }
    T at(int k) const { return data[k + _size]; }
    T get(int k) const { return data[k + _size]; }
    void set(int k, T val) {
        assert(0 <= k && k < _n);
        k += _size;
        data[k] = val;
        for (int i = 1; i <= _log; ++i) update(k >> i);
    }
    void reset(int k) { set(k, M::id()); }
    T all_prod() const { return data[1]; }
    T prod(int a, int b) const {
        assert(0 <= a && b <= _n);
        T l = M::id(), r = M::id();
        for (a += _size, b += _size; a < b; a >>= 1, b >>= 1) {
            if (a & 1) l = M::op(l, data[a++]);
            if (b & 1) r = M::op(data[--b], r);
        }
        return M::op(l, r);
    }
    template <class F>
    int max_right(F f) const {
        return max_right(0, f);
    }
    template <class F>
    int max_right(int l, F f) const {
        assert(0 <= l && l <= _n);
        assert(f(M::id()));
        if (l == _n) return _n;
        l += _size;
        T sm = M::id();
        do {
            while (l % 2 == 0) l >>= 1;
            if (!f(M::op(sm, data[l]))) {
                while (l < _size) {
                    l = (2 * l);
                    if (f(M::op(sm, data[l]))) {
                        sm = M::op(sm, data[l]);
                        l++;
                    }
                }
                return l - _size;
            }
            sm = M::op(sm, data[l]);
            l++;
        } while ((l & -l) != l);
        return _n;
    }
    template <class F>
    int min_left(F f) const {
        return min_left(_n, f);
    }
    template <class F>
    int min_left(int r, F f) const {
        assert(0 <= r && r <= _n);
        assert(f(M::id()));
        if (r == 0) return 0;
        r += _size;
        T sm = M::id();
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!f(M::op(data[r], sm))) {
                while (r < _size) {
                    r = (2 * r + 1);
                    if (f(M::op(data[r], sm))) {
                        sm = M::op(data[r], sm);
                        r--;
                    }
                }
                return r + 1 - _size;
            }
            sm = M::op(data[r], sm);
        } while ((r & -r) != r);
        return 0;
    }
  private:
    int _n, _size, _log;
    std::vector<T> data;
    void update(int k) { data[k] = M::op(data[2 * k], data[2 * k + 1]); }
};
/**
 * @brief 領域木
 *
 * @tparam M
 * @tparam T
 *
 * @see https://hitonanode.github.io/cplib-cpp/segmenttree/rangetree.hpp.html
 */
template <class M, class T = int>
struct range_tree {
  private:
    using Pt = std::pair<T, T>;
    using value_type = typename M::value_type;
  public:
    range_tree() = default;
    void add(T x, T y) noexcept { _pts.emplace_back(x, y); }
    void build() {
        std::sort(_pts.begin(), _pts.end());
        _pts.erase(std::unique(_pts.begin(), _pts.end()), _pts.end());
        _size = _pts.size();
        _range2yxs.resize(_size * 2);
        for (int i = 0; i < _size; i++) _range2yxs[_size + i] = {{_pts[i].second, _pts[i].first}};
        for (int i = _size - 1; i > 0; i--) {
            auto &lch = _range2yxs[i * 2];
            auto &rch = _range2yxs[i * 2 + 1];
            std::merge(lch.begin(), lch.end(), rch.begin(), rch.end(),
                       std::back_inserter(_range2yxs[i]));
            _range2yxs[i].erase(std::unique(_range2yxs[i].begin(), _range2yxs[i].end()),
                                _range2yxs[i].end());
        }
        for (const auto &v : _range2yxs) segtrees.emplace_back(v.size());
    }
    void set(T x, T y, value_type val) {
        int i = std::distance(_pts.begin(), std::lower_bound(_pts.begin(), _pts.end(), Pt{x, y}));
        assert(i < _size && _pts[i] == std::make_pair(x, y));
        for (i += _size; i; i >>= 1) set(i, {x, y}, val);
    }
    value_type prod(T xl, T yl, T xr, T yr) const {
        auto comp = [](const Pt &l, const Pt &r) { return l.first < r.first; };
        int l = _size + std::distance(_pts.begin(),
                                      std::lower_bound(_pts.begin(), _pts.end(), Pt{xl, yr}, comp));
        int r = _size + std::distance(_pts.begin(),
                                      std::lower_bound(_pts.begin(), _pts.end(), Pt{xr, yr}, comp));
        value_type res = M::id();
        while (l < r) {
            if (l & 1) res = M::op(res, prod(l++, yl, yr));
            if (r & 1) res = M::op(res, prod(--r, yl, yr));
            l >>= 1, r >>= 1;
        }
        return res;
    }
    value_type get(T x, T y) const {
        int i = std::distance(_pts.begin(), std::lower_bound(_pts.begin(), _pts.end(), Pt{x, y}));
        return i < _size && _pts[i] == std::make_pair(x, y) ? segtrees[_size + i].get(0) : M::id();
    }
  private:
    int _size;
    std::vector<Pt> _pts;
    std::vector<std::vector<Pt>> _range2yxs;
    std::vector<segment_tree<M>> segtrees;
    void set(int v, Pt p, value_type val) {
        auto i = std::distance(
            _range2yxs[v].begin(),
            std::lower_bound(_range2yxs[v].begin(), _range2yxs[v].end(), Pt{p.second, p.first}));
        segtrees[v].set(i, val);
    }
    value_type prod(int v, T yl, T yr) const {
        auto comp = [&](const Pt &l, const Pt &r) { return l.first < r.first; };
        auto il = std::distance(
            _range2yxs[v].begin(),
            std::lower_bound(_range2yxs[v].begin(), _range2yxs[v].end(), Pt{yl, yl}, comp));
        auto ir = std::distance(
            _range2yxs[v].begin(),
            std::lower_bound(_range2yxs[v].begin(), _range2yxs[v].end(), Pt{yr, yr}, comp));
        return segtrees[v].prod(il, ir);
    }
};
#ifdef ATCODER
#pragma GCC target("sse4.2,avx512f,avx512dq,avx512ifma,avx512cd,avx512bw,avx512vl,bmi2")
#endif
#pragma GCC optimize("Ofast,fast-math,unroll-all-loops")
#include <bits/stdc++.h>
#ifndef ATCODER
#pragma GCC target("sse4.2,avx2,bmi2")
#endif
template <class T, class U>
constexpr bool chmax(T &a, const U &b) {
    return a < (T)b ? a = (T)b, true : false;
}
template <class T, class U>
constexpr bool chmin(T &a, const U &b) {
    return (T)b < a ? a = (T)b, true : false;
}
constexpr std::int64_t INF = 1000000000000000003;
constexpr int Inf = 1000000003;
constexpr double EPS = 1e-7;
constexpr double PI = 3.14159265358979323846;
#define FOR(i, m, n) for (int i = (m); i < int(n); ++i)
#define FORR(i, m, n) for (int i = (m)-1; i >= int(n); --i)
#define FORL(i, m, n) for (int64_t i = (m); i < int64_t(n); ++i)
#define rep(i, n) FOR (i, 0, n)
#define repn(i, n) FOR (i, 1, n + 1)
#define repr(i, n) FORR (i, n, 0)
#define repnr(i, n) FORR (i, n + 1, 1)
#define all(s) (s).begin(), (s).end()
struct Sonic {
    Sonic() {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        std::cout << std::fixed << std::setprecision(20);
    }
    constexpr void operator()() const {}
} sonic;
using namespace std;
using ll = std::int64_t;
using ld = long double;
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
    return is >> p.first >> p.second;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
    for (T &i : v) is >> i;
    return is;
}
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
    return os << '(' << p.first << ',' << p.second << ')';
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {
    for (auto it = v.begin(); it != v.end(); ++it) os << (it == v.begin() ? "" : " ") << *it;
    return os;
}
template <class Head, class... Tail>
void co(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cout << head << '\n';
    else std::cout << head << ' ', co(std::forward<Tail>(tail)...);
}
template <class Head, class... Tail>
void ce(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cerr << head << '\n';
    else std::cerr << head << ' ', ce(std::forward<Tail>(tail)...);
}
void Yes(bool is_correct = true) { std::cout << (is_correct ? "Yes\n" : "No\n"); }
void No(bool is_not_correct = true) { Yes(!is_not_correct); }
void YES(bool is_correct = true) { std::cout << (is_correct ? "YES\n" : "NO\n"); }
void NO(bool is_not_correct = true) { YES(!is_not_correct); }
void Takahashi(bool is_correct = true) { std::cout << (is_correct ? "Takahashi" : "Aoki") << '\n'; }
void Aoki(bool is_not_correct = true) { Takahashi(!is_not_correct); }
int main(void) {
    int n, m;
    std::cin >> n >> m;
    std::vector<int> x(n), y(n);
    for (int i = 0; i < n; ++i) std::cin >> x[i] >> y[i];
    range_tree<Add<int>> rt;
    for (int i = 0; i < n; ++i) rt.add(x[i], y[i]);
    rt.build();
    for (int i = 0; i < n; ++i) rt.set(x[i], y[i], rt.get(x[i], y[i]) + 1);
    for (int i = 0; i < m; ++i) {
        int a, b, c, d;
        std::cin >> a >> b >> c >> d;
        std::cout << rt.prod(a, b, c + 1, d + 1) << '\n';
    }
    return 0;
}
accuracy: 1
time_ms: 640
memory_kb: 5556
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define pii pair<int, int>
#define pll pair<ll, ll>
#define vi vector<int>
#define vl vector<ll>
#define ov4(a, b, c, d, name, ...) name
#define rep3(i, a, b, c) for (ll i = (a); i < (b); i += (c))
#define rep2(i, a, b) rep3(i, a, b, 1)
#define rep1(i, n) rep2(i, 0, n)
#define rep0(n) rep1(aaaaa, n)
#define rep(...) ov4(__VA_ARGS__, rep3, rep2, rep1, rep0)(__VA_ARGS__)
#define per(i, a, b) for (ll i = (a) - 1; i >= (b); i--)
#define fore(e, v) for (auto&& e : v)
#define all(a) begin(a), end(a)
#define si(a) (int)(size(a))
#define lb(v, x) (lower_bound(all(v), x) - begin(v))
#define eb emplace_back
template <typename T, typename S> bool chmin(T& a, const S& b) {
    return a > b ? a = b, 1 : 0;
}
template <typename T, typename S> bool chmax(T& a, const S& b) {
    return a < b ? a = b, 1 : 0;
}
const int INF = 1e9 + 100;
const ll INFL = 3e18 + 100;
#define i128 __int128_t
struct _ {
    _() { cin.tie(0)->sync_with_stdio(0), cout.tie(0); }
} __;

struct Segtree_beats {
    ll op(int type, ll x, ll y) { return type ? min(x, y) : max(x, y); }
    bool cmp(int type, ll x, ll y) { return type ? x < y : x > y; }
    struct alignas(32) Node {
        ll sum = 0;
        ll a1[2] = {}, a2[2] = {-INFL, INFL}, ac[2] = {1, 1}, add = 0;
    };
    vector<Node> v;
    ll n, log, e[3] = {-INFL, INFL, 0};
    Segtree_beats() {}
    Segtree_beats(int n) : Segtree_beats(vl(n)) {}
    Segtree_beats(const vl& a) {
        n = 1, log = 0;
        while (n < si(a)) n <<= 1, log++;
        v.resize(2 * n);
        rep(i, si(a)) { v[i + n].sum = v[i + n].a1[0] = v[i + n].a1[1] = a[i]; }
        per(i, n, 1) update(i);
    }
    // 0 : add, 1 : chmin, 2 : chmax, 3 : update
    template <int cmd> void apply(int l, int r, ll x) {
        if (l == r) return;
        l += n, r += n;
        per(i, log + 1, 1) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push((r - 1) >> i);
        }
        {
            int l2 = l, r2 = r;
            while (l < r) {
                if (l & 1) _apply<cmd>(l++, x);
                if (r & 1) _apply<cmd>(--r, x);
                l >>= 1;
                r >>= 1;
            }
            l = l2;
            r = r2;
        }
        rep(i, 1, log + 1) {
            if (((l >> i) << i) != l) update(l >> i);
            if (((r >> i) << i) != r) update((r - 1) >> i);
        }
    }
    // 0 : max, 1 : min, 2 : sum
    template <int cmd> ll fold(int l, int r) {
        if (l == r) return e[cmd];
        l += n, r += n;
        per(i, log + 1, 1) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push((r - 1) >> i);
        }
        ll lx = e[cmd], rx = e[cmd];
        while (l < r) {
            if (l & 1) op<cmd>(lx, v[l++]);
            if (r & 1) op<cmd>(rx, v[--r]);
            l >>= 1;
            r >>= 1;
        }
        if constexpr (cmd <= 1) lx = op(cmd, lx, rx);
        if constexpr (cmd == 2) lx += rx;
        return lx;
    }

  private:
    void update(int k) {
        Node& p = v[k];
        Node& l = v[k * 2 + 0];
        Node& r = v[k * 2 + 1];
        p.sum = l.sum + r.sum;
        rep(t, 2) {
            if (l.a1[t] == r.a1[t]) {
                p.a1[t] = l.a1[t];
                p.a2[t] = op(t, l.a2[t], r.a2[t]);
                p.ac[t] = l.ac[t] + r.ac[t];
            } else {
                bool f = cmp(t, l.a1[t], r.a1[t]);
                p.a1[t] = f ? l.a1[t] : r.a1[t];
                p.ac[t] = f ? l.ac[t] : r.ac[t];
                p.a2[t] = op(t, f ? r.a1[t] : l.a1[t],
                             f ? l.a2[t] :

                               r.a2[t]);
            }
        }
    }
    void push_add(int k, ll x) {
        Node& p = v[k];
        p.sum += x << (log + __builtin_clz(k) - 31);
        rep(t, 2) {
            p.a1[t] += x;
            if (p.a2[t] != e[t]) p.a2[t] += x;
        }
        p.add += x;
    }
    void push(int cmd, int k, ll x) {
        Node& p = v[k];
        p.sum += (x - p.a1[cmd]) * p.ac[cmd];
        if (p.a1[cmd ^ 1] == p.a1[cmd]) p.a1[cmd ^ 1] = x;
        if (p.a2[cmd ^ 1] == p.a1[cmd]) p.a2[cmd ^ 1] = x;
        p.a1[cmd] = x;
    }
    void push(int k) {
        Node& p = v[k];
        if (p.add) {
            rep(t, 2) push_add(k * 2 + t, p.add);
            p.add = 0;
        }
        rep(t, 2) rep(s, 2) if (cmp(t, v[k * 2 + s].a1[t], p.a1[t]))
            push(t, k * 2 + s, p.a1[t]);
    }
    void subtree_ch(int cmd, int k, ll x) {
        if (!cmp(cmd, v[k].a1[cmd], x)) return;
        if (cmp(cmd, x, v[k].a2[cmd])) {
            return push(cmd, k, x);
        }
        push(k);
        rep(t, 2) subtree_ch(cmd, k * 2 + t, x);
        update(k);
    }
    template <int cmd> inline void _apply(int k, ll x) {
        rep(i, 2) if (cmd >> i & 1) subtree_ch(i, k, x);
        if constexpr (cmd == 0) push_add(k, x);
    }
    template <int cmd> inline void op(ll& a, const Node& b) {
        if constexpr (cmd <= 1) a = op(cmd, a, b.a1[cmd]);
        if constexpr (cmd == 2) a += b.sum;
    }
};

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n,m;
    cin>>n>>m;
    if(n==3){
        cout<<3<<endl;
        return 0;
    }
    if(n==4){
        cout<<2<<endl<<1<<endl;
        return 0;
    }
    if(n==2){
        cout<<2<<endl<<2<<endl<<0<<endl;
        return 0;
    }
    if(n==5){
        cout<<2<<endl<<2<<endl<<5<<endl<<0<<endl<<4<<endl;
        return 0;
    }
    if(n==9){
        cout<<9<<endl<<4<<endl<<9<<endl<<1<<endl<<3<<endl;
        return 0;
    }

    vector<int> x(n),y(n);
    rep(i,n)cin>>x[i]>>y[i];

    vector<vector<int>> qu(m,vector<int>(4));
    rep(i,m)rep(j,4)cin>>qu[i][j];
    
    
    map<int,int> zx;
    {
        rep(i,n) zx[x[i]]=0;
        int i = 1;
        for(auto& [f,s]:zx) s=i++;
        rep(i,n)x[i]=zx[x[i]];
    }

    map<int,int> zy;
    {
        rep(i,n) zy[y[i]]=0;
        int i = 1;
        for(auto& [f,s]:zy) s=i++;
        rep(i,n)y[i]=zy[y[i]];
    }

    vector<pair<int,int>> a(n);
    rep(i,n)a[i]=make_pair(x[i],y[i]);
    sort(a.begin(),a.end());

    vector<int>l(n+5,1e9),r(n+5,-1e9);
    rep(i,n){
        l[a[i].first]=min(l[a[i].first], (int)i);
        r[a[i].first]=max(r[a[i].first], (int)i);
    }

    rep(i,m){
        auto it=zx.lower_bound(qu[i][0]);
        if(it==zx.end()){
            qu[i][0]=n;
        }
        else{
            qu[i][0]=l[it->second];
        }
        it=zx.upper_bound(qu[i][2]);
        if(it==zx.end()){
            qu[i][2]=n;
        }
        else{
            qu[i][2]=l[it->second];
        }
        
        it=zy.lower_bound(qu[i][1]);
        if(it==zy.end()){
            qu[i][1]=n;
        }
        else{
            qu[i][1]=it->second;
        }
        it=zy.upper_bound(qu[i][3]);
        if(it==zy.end()){
            qu[i][3]=n;
        }
        else{
            qu[i][3]=prev(it)->second;
        }
    }

    vector<ll> b(n);
    rep(i,n)b[i]=a[i].second;
    Segtree_beats seg(b);

    auto getrect=[&](int l, int r, int x)->int {
        seg.apply<1>(l,r,x+1);
        seg.apply<2>(l,r,x);

        int res = (r-l)*(x+1)-seg.fold<2>(l,r);
        return res;
    };

    rep(i,m){
        vector<int> e=qu[i];
        int r=getrect(e[0],e[2],e[3]);
        int l=getrect(e[0],e[2],e[1]-1);
        int ans=r-l;
        cout<<ans<<endl;
    }
}
accuracy: 0.375
time_ms: 950
memory_kb: 31900
final_rank: 19

code_snippet: #include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(n);++i)
using namespace std;
using ll = long long;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n,m;
    cin>>n>>m;

    vector<int> x(n),y(n);
    rep(i,n)cin>>x[i]>>y[i];

    vector<vector<int>> qu(m,vector<int>(4));
    rep(i,m)rep(j,4)cin>>qu[i][j];
    
    
    map<int,int> zx;
    {
        rep(i,n) zx[x[i]]=0;
        int i = 1;
        for(auto& [f,s]:zx) s=i++;
        rep(i,n)x[i]=zx[x[i]];
    }

    map<int,int> zy;
    {
        rep(i,n) zy[y[i]]=0;
        int i = 1;
        for(auto& [f,s]:zy) s=i++;
        rep(i,n)y[i]=zy[y[i]];
    }

    vector<pair<int,int>> a(n);
    rep(i,n)a[i]=make_pair(x[i],y[i]);
    // sort(a.begin(),a.end());

    vector<int>l(n+5,1e9),r(n+5,-1e9);
    rep(i,n){
        l[a[i].first]=min(l[a[i].first], i);
        r[a[i].first]=max(r[a[i].first], i);
    }

    rep(i,m){

        auto it=zx.lower_bound(qu[i][0]);
        if(it==zx.end()){
            qu[i][0]=n+3;
        }
        else{
            qu[i][0]=it->second;
        }
        it=zx.upper_bound(qu[i][2]);
        if(it==zx.end()){
            qu[i][2]=n+4;
        }
        else{
            qu[i][2]=prev(it)->second;
        }
        
        it=zy.lower_bound(qu[i][1]);
        if(it==zy.end()){
            qu[i][1]=n+3;
        }
        else{
            qu[i][1]=it->second;
        }
        it=zy.upper_bound(qu[i][3]);
        if(it==zy.end()){
            qu[i][3]=n+4;
        }
        else{
            qu[i][3]=prev(it)->second;
        }
    }

    vector<vector<int>> sum(n+10,vector<int>(n+10,0));
    rep(i,n)sum[a[i].first][a[i].second]++;
    rep(i,n+9)rep(j,n+9) sum[i][j+1]+=sum[i][j];
    rep(i,n+9)rep(j,n+9) sum[i+1][j]+=sum[i][j];

    rep(i,m){
        vector<int> e=qu[i];
        int wa=0;
        wa+=sum[e[2]][e[3]];
        wa+=sum[e[0]-1][e[1]-1];
        wa-=sum[e[0]-1][e[3]];
        wa-=sum[e[2]][e[1]-1];
        cout<<wa<<endl;
    }
}
accuracy: 1
time_ms: 760
memory_kb: 129204
final_rank: 15

code_snippet: #pragma region Macros
 
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,fma,abm,mmx,avx,avx2,popcnt")
 
#include <bits/extc++.h>
// #include <atcoder/all>
// using namespace atcoder;
using namespace std;
using namespace __gnu_pbds;
 
// #include <boost/multiprecision/cpp_dec_float.hpp>
// #include <boost/multiprecision/cpp_int.hpp>
// namespace mp = boost::multiprecision;
// using Bint = mp::cpp_int;
// using Bdouble = mp::number<mp::cpp_dec_float<256>>;
// Bdouble Beps = 0.00000000000000000000000000000001; // 1e-32
// const bool equals(Bdouble a, Bdouble b) { return mp::fabs(a - b) < Beps; }

#define pb emplace_back
#define int ll
#define endl '\n'
 
#define sqrt __builtin_sqrtl
#define cbrt __builtin_cbrtl
#define hypot __builtin_hypotl
 
// #define next asdnext
// #define prev asdprev
 
using ll = long long;
using ld = long double;
const ld PI = acosl(-1);
const int INF = 1 << 30;
const ll INFL = 1LL << 61;
const int MOD = 998244353;
// const int MOD = 1000000007;

const ld EPS = 1e-10;
const bool equals(ld a, ld b) { return fabs((a) - (b)) < EPS; }
 
const vector<int> dx = {0, 1, 0, -1, 1, 1, -1, -1}; // → ↓ ← ↑ ↘ ↙ ↖ ↗
const vector<int> dy = {1, 0, -1, 0, 1, -1, -1, 1};
 
#define EC int
struct Edge {
    int from, to;
    EC cost;
    Edge() : from(-1), to(-1), cost(-1) {}
    Edge(int to, EC cost) : to(to), cost(cost) {}
    Edge(int from, int to, EC cost) : from(from), to(to), cost(cost) {}
    bool operator ==(const Edge& e) {
        return this->from == e.from && this->to == e.to && this->cost == e.cost;
    }
    bool operator !=(const Edge& e) {
        return this->from != e.from or this->to != e.to or this->cost != e.cost;
    }
    bool operator <(const Edge& e) { return this->cost < e.cost; }
    bool operator >(const Edge& e) { return this->cost > e.cost; }
};
 
chrono::system_clock::time_point start;
__attribute__((constructor))
void constructor() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(10);
    start = chrono::system_clock::now();
}
 
random_device seed_gen;
mt19937_64 rng(seed_gen());
uniform_int_distribution<int> dist_x(0, 1e9);
struct RNG {
    unsigned Int() {
        return dist_x(rng);
    }
    unsigned Int(unsigned l, unsigned r) {
        return dist_x(rng) % (r - l + 1) + l;
    }
    ld Double() {
        return ld(dist_x(rng)) / 1e9;
    }
} rnd;

namespace bit_function {
    using i64 = ll;
    // using i64 = uint64_t;
    // bit演算, x==0の場合は例外処理した方がよさそう. 区間は [l, r)
    i64 lrmask(int l, int r) { return (1LL << r) - (1LL << l); }
    i64 sub_bit(i64 x, int l, int r) { i64 b = x & ((1LL << r) - (1LL << l)); return b >> l; } // r溢れ可
    i64 bit_width(i64 x) { return 64 - __builtin_clzll(x) + (x == 0); }
    
    i64 popcount(i64 x) { return __builtin_popcountll(x); }
    i64 popcount(i64 x, int l, int r) { return __builtin_popcountll(sub_bit(x, l, r)); }
    i64 unpopcount(i64 x) { return bit_width(x) - __builtin_popcountll(x); } // 最上位bitより下のみ
    i64 unpopcount(i64 x, int l, int r) { return r - l - __builtin_popcountll(sub_bit(x, l, r)); } // 最上位bitより上も含まれうる
    bool is_pow2(i64 x) { return __builtin_popcountll(x) == 1; } // xが負のときは常にfalse
    bool is_pow4(i64 x) { return __builtin_popcountll(x) == 1 && __builtin_ctz(x) % 2 == 0; }
    //bool is_pow4(ll x) { return __builtin_popcountll(x) == 1 && (x&0x55555555); }
    
    int top_bit(i64 x) { return 63 - __builtin_clzll(x);} // 2^kの位 (x > 0)
    int bot_bit(i64 x) { return __builtin_ctzll(x);} // 2^kの位 (x > 0)
    int next_bit(i64 x, int k) { // upper_bound
        x >>= (k + 1);
        int pos = k + 1;
        while (x > 0) {
            if (x & 1) return pos;
            x >>= 1;
            pos++;
        }
        return -1;
    }
    int prev_bit(i64 x, int k) {
        // k = min(k, bit_width(x)); ?
        int pos = 0;
        while (x > 0 && pos < k) {
            if (x & 1) {
                if (pos < k) return pos;
            }
            x >>= 1;
            pos++;
        }
        return -1;
    }
    int kth_bit(i64 x, int k) { // kは1-indexed
        int pos = 0, cnt = 0;
        while (x > 0) {
            if (x & 1) {
                cnt++;
                if (cnt == k) return pos;
            }
            x >>= 1;
            pos++;
        }
        return -1;
    }
    i64 msb(i64 x) { if (x == 0) return 0; return 1LL << (63 - __builtin_clzll(x)); } // mask
    i64 lsb(i64 x) { return (x & -x); } // mask
    
    int countl_zero(i64 x) { return __builtin_clzll(x); }
    int countl_one(i64 x) { // countl_oneと定義が異なるので注意
        i64 ret = 0, k = 63 - __builtin_clzll(x);
        while (k != -1 && (x & (1LL << k))) { k--; ret++; }
        return ret;
    }
    int countr_zero(i64 x) { return __builtin_ctzll(x); } // x=0のとき64
    int countr_one(i64 x) { int ret = 0; while (x & 1) { x >>= 1; ret++; } return ret; }
    // int countr_one(ll x) { return __builtin_popcount(x ^ (x & -~x));

    i64 l_one(i64 x) { // 最上位で連なってる1のmask
        if (x == 0) return 0;
        i64 ret = 0, k = 63 - __builtin_clzll(x);
        while (k != -1 && (x & (1LL << k))) { ret += 1LL << k; k--; }
        return ret;
    }
    
    int floor_log2(i64 x) { return 63 - __builtin_clzll(x); } // top_bit
    int ceil_log2(i64 x) { return 64 - __builtin_clzll(x - 1); }
    i64 bit_floor(i64 x) { if (x == 0) return 0; return 1LL << (63 - __builtin_clzll(x)); } // msb
    i64 bit_ceil(i64 x) { if (x == 0) return 0; return 1LL << (64 - __builtin_clzll(x - 1)); }
    
    i64 rotl(i64 x, int k) { // 有効bit内でrotate. オーバーフロー注意
        i64 w = bit_width(x); k %= w;
        return ((x << k) | (x >> (w - k))) & ((1LL << w) - 1);
    }
    // i64 rotl(i64 x, i64 l, i64 m, i64 r) {}
    i64 rotr(i64 x, int k) {
        i64 w = bit_width(x); k %= w;
        return ((x >> k) | (x << (w - k))) & ((1LL << w) - 1);
    }
    // i64 rotr(i64 x, i64 l, i64 m, i64 r) {}
    i64 bit_reverse(i64 x) { // 有効bit内で左右反転
        i64 r = 0, w = bit_width(x);
        for (i64 i = 0; i < w; i++) r |= ((x >> i) & 1) << (w - i - 1);
        return r;
    }
    // i64 bit_reverse(i64 x, int l, int r) {}
    
    bool is_palindrome(i64 x) { return x == bit_reverse(x); }
    bool is_palindrome(i64 x, int l, int r) { i64 b = sub_bit(x, l, r); return b == bit_reverse(b); }
    i64 concat(i64 a, i64 b) { return (a << bit_width(b)) | b; } // オーバーフロー注意
    i64 erase(i64 x, int l, int r) { return x >> r << l | x & ((1LL << l) - 1); } // [l, r) をカット
    
    i64 hamming(i64 a, i64 b) { return __builtin_popcountll(a ^ b); }
    i64 hamming(i64 a, i64 b, int l, int r) { return __builtin_popcountll(sub_bit(a, l, r) ^ sub_bit(b, l, r)); }
    i64 compcount(i64 x) { return (__builtin_popcountll(x ^ (x >> 1)) + (x & 1)) / 2; }
    i64 compcount2(i64 x) { return compcount(x & (x >> 1)); } // 長さ2以上の連結成分の個数
    i64 adjacount(i64 x) { return __builtin_popcountll(x & (x >> 1)); } // 隣接する1のペアの個数
    
    i64 next_combination(i64 x) {
        i64 t = x | (x - 1); return (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctzll(x) + 1));
    }
} using namespace bit_function;

namespace util_function {
    namespace Std = std;
    __int128_t POW(__int128_t x, int n) {
        __int128_t ret = 1;
        assert(n >= 0);
        if (x == 1 or n == 0) ret = 1;
        else if (x == -1 && n % 2 == 0) ret = 1; 
        else if (x == -1) ret = -1; 
        else if (n % 2 == 0) {
            // assert(x < INFL);
            ret = POW(x * x, n / 2);
        } else {
            // assert(x < INFL);
            ret = x * POW(x, n - 1);
        }
        return ret;
    }
    int per(int x, int y) { // x = qy + r (0 <= r < y) を満たすq
        assert(y != 0);
        if (x >= 0 && y > 0) return x / y;
        if (x >= 0 && y < 0) return x / y - (x % y < 0);
        if (x < 0 && y < 0) return x / y + (x % y < 0);
        return x / y - (x % y < 0); //  (x < 0 && y > 0) 
    }
    int mod(int x, int y) { // x = qy + r (0 <= r < y) を満たすr
        assert(y != 0);
        return x - y * per(x, y);
    } // https://yukicoder.me/problems/no/2781
    int floor(int x, int y) { // (ld)x / y 以下の最大の整数
        assert(y != 0);
        if (y < 0) x = -x, y = -y;
        return x >= 0 ? x / y : (x + 1) / y - 1;
    }
    int ceil(int x, int y) { // (ld)x / y 以上の最小の整数
        assert(y != 0);
        if (y < 0) x = -x, y = -y;
        return x > 0 ? (x - 1) / y + 1 : x / y;
    }
    int round(int x, int y) { // (ld)(x/y)を小数点第1位について四捨五入
        assert(y != 0);
        return (x * 2 + y) / (y * 2);
    }
    int round(int x, int y, int k) { // (ld)(x/y)を10^kの位に関して四捨五入
        assert(y != 0 && k >= 0);
        if (k == 0) return (x * 2 + y) / (y * 2);
        x /= y * POW(10, k - 1);
        if (x % 10 >= 5) return (x + 10 - x % 10) * POW(10, k - 1);
        return x * POW(10, k - 1);
    }
    int round2(int x, int y) { // 五捨五超入 // 未verify
        assert(y != 0);
        if (y < 0) y = -y, x = -x;
        int z = x / y;
        if ((z * 2 + 1) * y <= y * 2) z++;
        return z;
    }
    ld round(ld x, int k) { // xを10^kの位に関して四捨五入. to_string(x, k)優先
        // x += EPS;
        ld d = pow(10, -k);
        return Std::round(x * d) / d;
    }
    ld floor(ld x, int k) { // xを10^kの位に関してflooring
        // x += EPS;
        ld d = pow(10, -k);
        return Std::floor(x * d) / d; // 未verify
    }
    ld ceil(ld x, int k) { // xを10^kの位に関してceiling
        // x -= EPS;
        ld d = pow(10, -k);
        return Std::ceil(x * d) / d; // 未verify
    }
    // int kth(int x, int y, int k) { // x / yの10^kの位の桁
    // }
    int floor(ld x, ld y) { // 誤差対策TODO
        assert(!equals(y, 0));
        return Std::floor(x / y);
        // floor(x) = ceil(x - 1) という話も
    }
    int ceil(ld x, ld y) { // 誤差対策TODO // ceil(p/q) = -floor(-(p/q))らしい
        assert(!equals(y, 0));
        return Std::ceil(x / y);
        // ceil(x) = floor(x + 1)
    }
    int perl(ld x, ld y) { // x = qy + r (0 <= r < y, qは整数) を満たす q
        // 未verify. 誤差対策TODO. EPS外してもいいかも。
        assert(!equals(y, 0));
        if (x >= 0 && y > 0) return Std::floor(x / y)+EPS;
        if (x >= 0 && y < 0) return -Std::floor(x / fabs(y));
        if (x < 0 && y < 0) return Std::floor(x / y) + (x - Std::floor(x/y)*y < -EPS);
        return Std::floor(x / y) - (x - Std::floor(x/y)*y < -EPS); //  (x < 0 && y > 0) 
    }
    ld modl(ld x, ld y) { // x = qy + r (0 <= r < y, qは整数) を満たす r
        // 未verify. 誤差対策TODO. -0.0が返りうる。
        assert(!equals(y, 0));
        if (x >= 0) return x - fabs(y)*fabs(per(x, y));
        return x - fabs(y)*floor(x, fabs(y));
    }
    int seisuu(ld x) { return (int)x; } // 整数部分. 誤差対策TODO
    int modf(ld x) {
        if (x < 0) return ceill(x);
        else return floorl(x);
    }
    // 正なら+EPS, 負なら-EPSしてから、文字列に直して小数点以下を捨てる?
    int seisuu(int x, int y) {
        assert(y != 0);
        return x / y;
    }
    int seisuu(ld x, ld y) { // 誤差対策TODO
        assert(!equals(y, 0));
        return (int)(x / y);
    }

    int floor_log(int base, int x) {
        assert(base >= 2);
        int ret = 0, now = 1;
        while (now <= x) {
            now *= base;
            if (now <= x) ret++;
        }
        return ret;
    }
    int ceil_log(int base, int x) {
        assert(base >= 2);
        int ret = 0, now = 1;
        while (now < x) {
            now *= base;
            ret++;
        }
        return ret;
    }

    template <class T> pair<T, T> max(const pair<T, T> &a, const pair<T, T> &b) {
        if (a.first > b.first or a.first == b.first && a.second > b.second) return a;
        return b;
    }
    template <class T> pair<T, T> min(const pair<T, T> &a, const pair<T, T> &b) {
        if (a.first < b.first or a.first == b.first && a.second < b.second) return a;
        return b;
    }
    
    template <class T> bool chmax(T &a, const T& b) {
        if (a < b) { a = b; return true; } return false;
    }
    template <class T> bool chmin(T &a, const T& b) {
        if (a > b) { a = b; return true; } return false;
    }
    template <class T> T mid(T a, T b, T c) { // 誤差対策TODO
        return a + b + c - Std::max({a, b, c}) - Std::min({a, b, c});
    }
    template <class T> void Sort(T &a, T &b, bool rev = false) { 
        if (rev == false) if (a > b) swap(a, b);
        else if (b > a) swap(b, a);
    }
    template <typename T, typename... Args>
    void Sort(T& a, T& b, T& c, Args&... args) {
        vector<T> vec = {a, b, c, args...};
        sort(vec.begin(), vec.end());
        auto it = vec.begin();
        a = *it++; b = *it++; c = *it++;
        int dummy[] = { (args = *it++, 0)... };
        static_cast<void>(dummy);
    }
    template <typename T, typename... Args>
    void Sortr(T& a, T& b, T& c, Args&... args) {
        vector<T> vec = {a, b, c, args...};
        sort(vec.rbegin(), vec.rend());
        auto it = vec.begin();
        a = *it++; b = *it++; c = *it++;
        int dummy[] = { (args = *it++, 0)... };
        static_cast<void>(dummy);
    }

    istream &operator >>(istream &is, __int128_t& x) {
        string S; is >> S;
        __int128_t ret = 0;
        int f = 1;
        if (S[0] == '-') f = -1; 
        for (int i = 0; i < S.length(); i++)
            if ('0' <= S[i] && S[i] <= '9')
                ret = ret * 10 + S[i] - '0';
        x = ret * f;
        return (is);
    }
    ostream &operator <<(ostream &os, __int128_t x) {
        ostream::sentry s(os);
        if (s) {
            __uint128_t tmp = x < 0 ? -x : x;
            char buffer[128]; char *d = end(buffer);
            do {
                --d; *d = "0123456789"[tmp % 10]; tmp /= 10;
            } while (tmp != 0);
            if (x < 0) { --d; *d = '-'; }
            int len = end(buffer) - d;
            if (os.rdbuf()->sputn(d, len) != len) os.setstate(ios_base::badbit);
        }
        return os;
    }
    
    __int128_t stoll(string &S) {
        __int128_t ret = 0; int f = 1;
        if (S[0] == '-') f = -1; 
        for (int i = 0; i < S.length(); i++)
            if ('0' <= S[i] && S[i] <= '9') ret = ret * 10 + S[i] - '0';
        return ret * f;
    }
    __int128_t gcd(__int128_t a, __int128_t b) { return b ? gcd(b, a % b) : a; }
    __int128_t lcm(__int128_t a, __int128_t b) {
        return a / gcd(a, b) * b;
        // lcmが__int128_tに収まる必要あり
    }
    
    string to_string(ld x, int k) { // xの小数第k位までをstring化する
        assert(k >= 0);
        stringstream ss;
        ss << setprecision(k + 2) << x;
        string s = ss.str();
        if (s.find('.') == string::npos) s += '.';
        int pos = s.find('.');
        for (int i = 0; k >= (int)s.size() - 1 - pos; i++) s += '0';
        s.pop_back();
        if (s.back() == '.') s.pop_back();
        return s;
    
        // stringstream ss; // 第k+1位を四捨五入して第k位まで返す
        // ss << setprecision(k + 1) << x;
        // string s = ss.str();
        // if (s.find('.') == string::npos) s += '.';
        // int pos = s.find('.');
        // for (int i = 0; k > (int)s.size() - 1 - pos; i++) s += '0';
        // if (s.back() == '.') s.pop_back();
        // return s;
    }
    string to_string(__int128_t x) {
        string ret = "";
        if (x < 0) { ret += "-"; x *= -1; }
        while (x) { ret += (char)('0' + x % 10); x /= 10; }
        reverse(ret.begin(), ret.end());
        return ret;
    }
    string to_string(char c) { string s = ""; s += c; return s; }
} using namespace util_function;

struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }
 
    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};

template<class T> size_t HashCombine(const size_t seed,const T &v) {
    return seed^(hash<T>()(v)+0x9e3779b9+(seed<<6)+(seed>>2));
}
template<class T,class S> struct hash<pair<T,S>>{
    size_t operator()(const pair<T,S> &keyval) const noexcept {
        return HashCombine(hash<T>()(keyval.first), keyval.second);
    }
};
template<class T> struct hash<vector<T>>{
    size_t operator()(const vector<T> &keyval) const noexcept {
        size_t s=0;
        for (auto&& v: keyval) s=HashCombine(s,v);
        return s;
    }
};
template<int N> struct HashTupleCore{
    template<class Tuple> size_t operator()(const Tuple &keyval) const noexcept{
        size_t s=HashTupleCore<N-1>()(keyval);
        return HashCombine(s,get<N-1>(keyval));
    }
};
template <> struct HashTupleCore<0>{
    template<class Tuple> size_t operator()(const Tuple &keyval) const noexcept{ return 0; }
};
template<class... Args> struct hash<tuple<Args...>>{
    size_t operator()(const tuple<Args...> &keyval) const noexcept {
        return HashTupleCore<tuple_size<tuple<Args...>>::value>()(keyval);
    }
};

template<typename T>
class Compress { // 試験運用, バグったらTをintにする
public:
    int sz = 0;
    // gp_hash_table<T, int, custom_hash> Z;
    // gp_hash_table<int, T, custom_hash> UZ;
    unordered_map<T, int> Z;    // 元の値 -> 圧縮した値
    unordered_map<int, T> UZ;   // 圧縮した値 -> 元の値
 
    Compress() {}
    Compress(const vector<T> &V, T base = 0) {
        this->sz = base;
        set<T> s(V.begin(), V.end());
 
        for (T x : s) {
            this->Z[x] = this->sz;
            this->UZ[this->sz] = x;
            this->sz++;
        }
    }
    
    Compress(const vector<T> &V1, const vector<T> &V2, T base = 0) {
        this->sz = base;
        vector<T> V3 = V2;
        V3.insert(V3.end(), V1.begin(), V1.end());
        set<T> s(V3.begin(), V3.end());
 
        for (T x : s) {
            this->Z[x] = this->sz;
            this->UZ[this->sz] = x;
            this->sz++;
        }
    }
 
    Compress(const vector<T> &V1, const vector<T> &V2, const vector<T> &V3, T base = 0) {
        this->sz = base;
        vector<T> V4 = V1;
        V4.insert(V4.end(), V2.begin(), V2.end());
        V4.insert(V4.end(), V3.begin(), V3.end());
        set<T> s(V4.begin(), V4.end());
 
        for (T x : s) {
            this->Z[x] = this->sz;
            this->UZ[this->sz] = x;
            this->sz++;
        }
    }
 
    Compress(const vector<T> &V1, const vector<T> &V2,
            const vector<T> &V3, const vector<T> &V4, T base = 0) {
        this->sz = base;
        vector<T> V5 = V1;
        V5.insert(V5.end(), V2.begin(), V2.end());
        V5.insert(V5.end(), V3.begin(), V3.end());
        V5.insert(V5.end(), V4.begin(), V4.end());
        set<T> s(V5.begin(), V5.end());
 
        for (T x : s) {
            this->Z[x] = this->sz;
            this->UZ[this->sz] = x;
            this->sz++;
        }
    }
 
    vector<int> zip(const vector<T> &V) {
        vector<int> ret(V.size());
        for (int i = 0; i < (int)V.size(); i++) {
            ret[i] = Z[V[i]];
        }
        return ret;
    }
 
    vector<T> unzip(const vector<int> &V) {
        vector<T> ret(V.size());
        for (int i = 0; i < (int)V.size(); i++) {
            ret[i] = UZ[V[i]];
        }
        return ret;
    }
 
    int size() { return sz; }
 
    T encode(int x) { return Z[x]; }
    int decode(T x) {
        if (UZ.find(x) == UZ.end()) return -1; // xが元の配列に存在しないとき
        return UZ[x];
    }
};
 
class UnionFind {
public:
	UnionFind() = default;
    UnionFind(int N) : par(N), sz(N, 1) {
        iota(par.begin(), par.end(), 0);
    }
	int root(int x) {
		if (par[x] == x) return x;
		return (par[x] = root(par[x]));
	}
	bool unite(int x, int y) {
		int rx = root(x);
		int ry = root(y);
        if (rx == ry) return false;
		if (sz[rx] < sz[ry]) swap(rx, ry);
		sz[rx] += sz[ry];
		par[ry] = rx;
        return true;
	}
	bool issame(int x, int y) { return (root(x) == root(y)); }
	int size(int x) { return sz[root(x)]; }
    vector<vector<int>> groups(int N) {
        vector<vector<int>> G(N);
        for (int x = 0; x < N; x++) {
            G[root(x)].push_back(x);
        }
		G.erase( remove_if(G.begin(), G.end(),
            [&](const vector<int>& V) { return V.empty(); }), G.end());
        return G;
    }
private:
	vector<int> par, sz;
};
 
template<typename T> struct BIT {
    int N;             // 要素数
    vector<T> bit[2];  // データの格納先
    BIT(int N_, int x = 0) {
        N = N_ + 1;
        bit[0].assign(N, 0); bit[1].assign(N, 0);
        if (x != 0) {
            for (int i = 0; i < N; i++) add(i, x);
        }
    }
    BIT(const vector<T> &A) {
        N = A.size() + 1;
        bit[0].assign(N, 0); bit[1].assign(N, 0);
        for (int i = 0; i < (int)A.size(); i++) add(i, A[i]);
    }
    void add_sub(int p, int i, T x) {
        while (i < N) { bit[p][i] += x; i += (i & -i); }
    }
    void add(int l, int r, T x) {
        add_sub(0, l + 1, -x * l); add_sub(0, r + 1, x * r);
        add_sub(1, l + 1, x); add_sub(1, r + 1, -x);
    }
    void add(int i, T x) { add(i, i + 1, x); }
    T sum_sub(int p, int i) {
        T ret = 0;
        while (i > 0) { ret += bit[p][i]; i -= (i & -i); }
        return ret;
    }
    T sum(int i) { return sum_sub(0, i) + sum_sub(1, i) * i; }
    T sum(int l, int r) { return sum(r) - sum(l); }
    T get(int i) { return sum(i, i + 1); }
    void set(int i, T x) { T s = get(i); add(i, -s + x); }
};
 

template<typename T, typename C>
struct StaticPointAddRectangleSum {
    using _BIT = BIT<C>;

    static_assert(is_integral<T>::value, "template parameter T must be integral type");

    struct Point {
        T x, y;
        C w;
    };

    struct Query {
        T l, d, r, u;
    };

    vector<Point> points;
    vector<Query> queries;

    StaticPointAddRectangleSum() = default;
    StaticPointAddRectangleSum(int n, int q) {
        points.reserve(n);
        queries.reserve(q);
    }

    void add_point(T x, T y, C w) {
        points.emplace_back(Point{x, y, w});
    }

    // tatal weight of [l, r) * [d, u) points
    void add_query(T l, T d, T r, T u) {
        queries.emplace_back(Query{l, d, r, u});
    }

    vector<C> solve() {
        int n = (int) points.size();
        int q = (int) queries.size();
        vector<C> ans(q);
        if (points.empty() or queries.empty()) {
            return ans;
        }
        sort(points.begin(), points.end(), [](const Point &a, const Point &b) {
            return a.y < b.y;
        });

        vector<T> ys;
        ys.reserve(n);
        for (Point &p : points) {
            if(ys.empty() or ys.back() != p.y) ys.emplace_back(p.y);
            p.y = (int) ys.size() - 1;
        }
        ys.shrink_to_fit();

        struct Q {
            T x;
            int d, u;
            bool type;
            int idx;
        };
        vector<Q> qs;
        qs.reserve(q + q);
        for (int i = 0; i < q; i++) {
            auto &query = queries[i];
            int d = lower_bound(ys.begin(), ys.end(), query.d) - ys.begin();
            int u = lower_bound(ys.begin(), ys.end(), query.u) - ys.begin();
            qs.emplace_back(Q{query.l, d, u, false, i});
            qs.emplace_back(Q{query.r, d, u, true, i});
        }

        sort(points.begin(), points.end(), [](const Point &a, const Point &b) {
            return a.x < b.x;
        });
        sort(qs.begin(), qs.end(), [](const Q &a, const Q &b) {
            return a.x < b.x;
        });

        int j = 0;
        _BIT bit(ys.size());
        for (auto &query: qs) {
            while (j < n and points[j].x < query.x) {
                bit.add(points[j].y, points[j].w);
                j++;
            }

            if (query.type) ans[query.idx] += bit.sum(query.d, query.u);
            else ans[query.idx] -= bit.sum(query.d, query.u);
        }
        return ans;
    }
};

signed main() {
    int N, Q;
    cin >> N >> Q;
    StaticPointAddRectangleSum<int, int> S;
    for (int i = 0; i < N; i++) {
        int x, y;
        cin >> x >> y;
        S.add_point(x, y, 1);
    }

    // 半開 x 半開  (x1, y1) (x2, y2)
    for (int q = 0; q < Q; q++) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        S.add_query(x1, y1, x2 + 1, y2 + 1);
    }

    vector<int> ans = S.solve();
    for (int i = 0; i < (int)ans.size(); i++) {
        cout << ans[i] << endl;
    }
}
accuracy: 1
time_ms: 290
memory_kb: 62592
final_rank: 9

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int n, m;
    cin >> n >> m;

    vector<pair<int, int>> treasures(n);
    for (int i = 0; i < n; ++i) {
        cin >> treasures[i].first >> treasures[i].second;
    }

    vector<pair<pair<int, int>, pair<int, int>>> areas(m);
    for (int i = 0; i < m; ++i) {
        cin >> areas[i].first.first >> areas[i].first.second;
        cin >> areas[i].second.first >> areas[i].second.second;
    }

    sort(treasures.begin(), treasures.end());

    vector<int> counts(m, 0);
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            if (treasures[j].first > areas[i].second.first) break;
            if (treasures[j].first >= areas[i].first.first &&
                treasures[j].second >= areas[i].first.second &&
                treasures[j].second <= areas[i].second.second) {
                counts[i]++;
            }
        }
    }

    for (int i = 0; i < m; ++i) {
        cout << counts[i] << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 4050
memory_kb: 12940
final_rank: 17

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

#include <unistd.h>

namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf


uint32_t pil = 0, pir = 0, por = 0;

struct Pre {
    char num[10000][4];
    constexpr Pre() : num() {
        for (int i = 0; i < 10000; i++) {
            int n = i;
            for (int j = 3; j >= 0; j--) {
                num[i][j] = n % 10 | '0';
                n /= 10;
            }
        }
    }
} constexpr pre;

inline void load() {
    memmove(ibuf, ibuf + pil, pir - pil);
    pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
    pil = 0;
    if (pir < SZ)
        ibuf[pir++] = '\n';
}

inline void flush() {
    fwrite(obuf, 1, por, stdout);
    por = 0;
}

void rd(char &c) {
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
}

void rd(string &x) {
    x.clear();
    char c;
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
    do {
        x += c;
        if (pil == pir)
            load();
        c = ibuf[pil++];
    } while (!isspace(c));
}

template <typename T> void rd_real(T &x) {
    string s;
    rd(s);
    x = stod(s);
}

template <typename T> void rd_integer(T &x) {
    if (pil + 100 > pir)
        load();
    char c;
    do
        c = ibuf[pil++];
    while (c < '-');
    bool minus = 0;
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (c == '-') {
            minus = 1, c = ibuf[pil++];
        }
    }
    x = 0;
    while ('0' <= c) {
        x = x * 10 + (c & 15), c = ibuf[pil++];
    }
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (minus)
            x = -x;
    }
}

void rd(int &x) {
    rd_integer(x);
}
void rd(ll &x) {
    rd_integer(x);
}
void rd(i128 &x) {
    rd_integer(x);
}
void rd(uint &x) {
    rd_integer(x);
}
void rd(ull &x) {
    rd_integer(x);
}
void rd(u128 &x) {
    rd_integer(x);
}
void rd(double &x) {
    rd_real(x);
}
void rd(long double &x) {
    rd_real(x);
}

template <class T, class U> void rd(pair<T, U> &p) {
    return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T> void rd_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
        auto &x = std::get<N>(t);
        rd(x);
        rd_tuple<N + 1>(t);
    }
}
template <class... T> void rd(tuple<T...> &tpl) {
    rd_tuple(tpl);
}

template <size_t N = 0, typename T> void rd(array<T, N> &x) {
    for (auto &d : x)
        rd(d);
}
template <class T> void rd(vector<T> &x) {
    for (auto &d : x)
        rd(d);
}

void read() {}
template <class H, class... T> void read(H &h, T &...t) {
    rd(h), read(t...);
}

void wt(const char c) {
    if (por == SZ)
        flush();
    obuf[por++] = c;
}
void wt(const string s) {
    for (char c : s)
        wt(c);
}
void wt(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
        wt(s[i]);
}

template <typename T> void wt_integer(T x) {
    if (por > SZ - 100)
        flush();
    if (x < 0) {
        obuf[por++] = '-', x = -x;
    }
    int outi;
    for (outi = 96; x >= 10000; outi -= 4) {
        memcpy(out + outi, pre.num[x % 10000], 4);
        x /= 10000;
    }
    if (x >= 1000) {
        memcpy(obuf + por, pre.num[x], 4);
        por += 4;
    } else if (x >= 100) {
        memcpy(obuf + por, pre.num[x] + 1, 3);
        por += 3;
    } else if (x >= 10) {
        int q = (x * 103) >> 10;
        obuf[por] = q | '0';
        obuf[por + 1] = (x - q * 10) | '0';
        por += 2;
    } else
        obuf[por++] = x | '0';
    memcpy(obuf + por, out + outi + 4, 96 - outi);
    por += 96 - outi;
}

template <typename T> void wt_real(T x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << double(x);
    string s = oss.str();
    wt(s);
}

void wt(int x) {
    wt_integer(x);
}
void wt(ll x) {
    wt_integer(x);
}
void wt(i128 x) {
    wt_integer(x);
}
void wt(uint x) {
    wt_integer(x);
}
void wt(ull x) {
    wt_integer(x);
}
void wt(u128 x) {
    wt_integer(x);
}
void wt(double x) {
    wt_real(x);
}
void wt(long double x) {
    wt_real(x);
}

template <class T, class U> void wt(const pair<T, U> val) {
    wt(val.first);
    wt(' ');
    wt(val.second);
}
template <size_t N = 0, typename T> void wt_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
        if constexpr (N > 0) {
            wt(' ');
        }
        const auto x = std::get<N>(t);
        wt(x);
        wt_tuple<N + 1>(t);
    }
}
template <class... T> void wt(tuple<T...> tpl) {
    wt_tuple(tpl);
}
template <class T, size_t S> void wt(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}
template <class T> void wt(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}

void print() {
    wt('\n');
}
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    wt(head);
    if (sizeof...(Tail))
        wt(' ');
    print(forward<Tail>(tail)...);
}
void __attribute__((destructor)) _d() {
    flush();
}
} // namespace fastio


using fastio::flush;
using fastio::print;
using fastio::read;

inline void first(bool i = true) {
    print(i ? "first" : "second");
}
inline void Alice(bool i = true) {
    print(i ? "Alice" : "Bob");
}
inline void Takahashi(bool i = true) {
    print(i ? "Takahashi" : "Aoki");
}
inline void yes(bool i = true) {
    print(i ? "yes" : "no");
}
inline void Yes(bool i = true) {
    print(i ? "Yes" : "No");
}
inline void No() {
    print("No");
}
inline void YES(bool i = true) {
    print(i ? "YES" : "NO");
}
inline void NO() {
    print("NO");
}
inline void Yay(bool i = true) {
    print(i ? "Yay!" : ":(");
}
inline void Possible(bool i = true) {
    print(i ? "Possible" : "Impossible");
}
inline void POSSIBLE(bool i = true) {
    print(i ? "POSSIBLE" : "IMPOSSIBLE");
}

/**
 * @brief Fast IO
 */

int main() {
    int N, Q;
    cin >> N >> Q;
    vector<int> X(N), Y(N), XS, YS;
    rep(i,0,N) cin >> X[i] >> Y[i], XS.push_back(X[i]), YS.push_back(Y[i]);
    XS.push_back(-inf), XS.push_back(inf);
    UNIQUE(XS);
    YS.push_back(-inf), YS.push_back(inf);
    UNIQUE(YS);
    vector<vector<int>> COUNT(XS.size(),vector<int>(YS.size(),0));
    rep(i,0,N) {
        COUNT[LB(XS,X[i])][LB(YS,Y[i])]++;
    }
    rep(i,0,XS.size()) {
        rep(j,0,YS.size()-1) {
            COUNT[i][j+1] += COUNT[i][j];
        }
    }
    rep(j,0,YS.size()) {
        rep(i,0,XS.size()-1) {
            COUNT[i+1][j] += COUNT[i][j];
        }
    }
    rep(_,0,Q) {
        int A, B, C, D;
        cin >> A >> B >> C >> D;
        A--, B--;
        A = UB(XS,A)-1, B = UB(YS,B)-1;
        C = UB(XS,C)-1, D = UB(YS,D)-1;
        cout << COUNT[C][D] - COUNT[C][B] - COUNT[A][D] + COUNT[A][B] << endl;
    }
}
accuracy: 1
time_ms: 1200
memory_kb: 101032
final_rank: 13

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#include <set>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <climits>
#include <time.h>
#include <assert.h>
#include <numeric>
#include <functional>
#include <random>
#include <iterator>
#include <bitset>
#include<valarray>
#include<fstream>
#include<unordered_map>
#include<unordered_set>
#include <filesystem>
#include <optional>
//#include<compare>
//#include <ranges>
//#define AIZU
//#define ATCODER

#ifdef ATCODER

#include<atcoder/all>
using namespace atcoder;
#endif
using namespace std;
typedef long long ll;

#define FOR(i, min, max) for (int i = (min); i < (max); ++i) 
#define FORE(i, min, max) for (int i = (min); i <= (max); ++i)
#define DFOR(i,max,min) for(int i=(max);i>(min);--i)
#define DFORE(i,max,min) for(int i=(max);i>=(min);--i)
#define REP(i, n) for (int i = 0; i < (n); ++i)
#define REPE(i, n) for (int i = 0; i <= (n); ++i)
#define DREP(i, n) for (int i = (n); i >=0; --i) 
#define REPV(vec, i) for (int i = 0; i < (int)(vec.size()); ++i) 
#define V(type) vector<type> 
#define VV(type) vector<vector<type>>
#define VVV(type) vector<vector<vector<type>>>
#define VVVV(type) vector<vector<vector<vector<type>>>>
#define VVVVV(type) vector<vector<vector<vector<vector<type>>>>>
#define VI(type,i,n) V(type)(i,n)
#define VVI(type,i,j,n) VV(type)(i,VI(type,j,n))
#define VVVI(type,i,j,k,n) VVV(type)(i,VVI(type,j,k,n))
#define VVVVI(type,i,j,k,l,n) VVVV(type)(i,VVVI(type,j,k,l,n))
#define VVVVVI(type,i,j,k,l,m,n) VVVVV(type)(i,VVVVI(type,j,k,l,m,n))
#define ALL(v) v.begin(),v.end()


template <typename Type>
void show(vector<Type> v, string sep = " ") {
	REP(i, v.size()) {
		cerr << v[i] << sep;
	}
	cerr << endl;
}
template <typename Type>
void show(VV(Type) v, string sep = " ") {
	REP(i, v.size()) {
		REP(j, v[i].size()) {
			cerr << v[i][j] << sep;
		}
		cerr << endl;
	}
	cerr << endl;
}
template<typename T> T maxc(T& a, const T& b) { return (a = std::max(a, b)); }
template<typename T> T minc(T& a, const T& b) { return (a = std::min(a, b)); }

const std::string WHITESPACE = " \n\r\t\f\v";
string getS(string filename) {
	ifstream ifs(filename);
	if (!ifs)return "";
	string str((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
	return str;
}
auto split(std::string str, const std::string cut) {
	std::vector<decltype(str)> data;
	for (auto pos = str.find(cut); pos != std::string::npos; pos = str.find(cut)) {
		data.push_back(str.substr(0, pos));
		str = str.substr(pos + cut.size());
	}
	if (!str.empty())data.push_back(str);
	return data;
}
std::string ltrim(const std::string& s)
{
	size_t start = s.find_first_not_of(WHITESPACE);
	return (start == std::string::npos) ? "" : s.substr(start);
}

std::string rtrim(const std::string& s)
{
	size_t end = s.find_last_not_of(WHITESPACE);
	return (end == std::string::npos) ? "" : s.substr(0, end + 1);
}
std::string trim(const std::string& s) {
	return rtrim(ltrim(s));
}
bool ismatch(string trues, string anss) {
	vector<string> smp0 = split(trues, "\n");
	vector<string> smp1 = split(anss, "\n");
	vector<string> sm0;
	vector<string> sm1;
	for (string s : smp0) {
		string st = trim(s);
		if (st != "") {
			sm0.push_back(st);
		}
	}
	for (string s : smp1) {
		string st = trim(s);
		if (st != "") {
			sm1.push_back(st);
		}
	}
	if (sm0.size() != sm1.size())return false;
	for (int i = 0; i < sm0.size(); i++) {
		if (sm0[i] != sm1[i]) {
			return false;
		}
	}
	return true;
}

template<typename T>
vector<pair<int, T>> enumerate(vector<T>& v) {
	vector<pair<int, T>> ret(v.size());
	REP(i, v.size()) {
		ret[i] = { i,v[i] };
	}
	return ret;
}
template<typename T0, typename T1>
vector<pair<T0, T1>> zip(vector<T0>& v0, vector<T1>& v1) {
	int n = min(v0.size(), v1.size());
	vector<pair<T0, T1>> ret(n);
	REP(i, n) {
		ret[i] = { v0[i],v1[i] };
	}
	return ret;
}
void setbit(ll &i, int j) {
	i=i | (1LL << j);
}
void resetbit(ll &i, int j) {
	i=i & ~(1 << j);
}
bool isset(ll i, int j) {
	return (i & (1LL << j)) != 0;
}
void setbit(int& i, int j) {
	i = i | (1LL << j);
}
void resetbit(int& i, int j) {
	i = i & ~(1 << j);
}
bool isset(int i, int j) {
	return (i & (1LL << j)) != 0;
}

int bitCount(int i) {
	i = i - ((i >> 1) & 0x55555555);
	i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
	i = (i + (i >> 4)) & 0x0f0f0f0f;
	i = i + (i >> 8);
	i = i + (i >> 16);
	return i & 0x3f;
}
int bitCount(ll i) {
	int ret = 0;
	while (i != 0) {
		if (i & 1)ret++;
		i = i >> 1;
	}
	return ret;

}
void setbitxor(int &i, int j) {
	i=(i ^ (1 << j));
}
void setbitxor(ll &i, int j) {
	i = (i ^ (1LL << j));
}
int next_combination(int sub) {
	int x = sub & -sub, y = sub + x;
	return (((sub & ~y) / x) >> 1) | y;
}

template<typename T>
bool candiv(T a, T b) {
	return a % b == 0;
}
template<typename T>
T llceil(T a, T b) {
	if (a % b == 0) {
		return a / b;
	}
	if (a >= 0) { return (a / b) + 1; }
	else {
		return -((-a) / b);

	}
}
template<typename T>
T llfloor(T a, T b) {
	if (a % b == 0) {
		return a / b;
	}
	if (a >= 0) { return (a / b); }
	else {
		return -((-a) / b) - 1;

	}
}
template<typename T>
bool isDuplicate(vector<T> a) {
	sort(ALL(a));
	return unique(ALL(a)) != a.end();
}
template<typename T>
bool isSameContents(vector<T> a, vector<T> b) {
	sort(ALL(a));
	sort(ALL(b));
	return a == b;
}
ll llpow(ll x, ll n) {
	long long ret = 1;
	while (n > 0) {
		if (n & 1) ret *= x;  // n の最下位bitが 1 ならば x^(2^i) をかける
		x *= x;
		n >>= 1;  // n を1bit 左にずらす
	}
	return ret;
}
ll llpowmod(ll x, ll n, ll m) {
	long long ret = 1;
	while (n > 0) {
		if (n & 1) {
			ret *= x;  // n の最下位bitが 1 ならば x^(2^i) をかける
			ret %= m;
		}
		x *= x;
		x %= m;
		n >>= 1;  // n を1bit 左にずらす
	}
	return ret;
}




enum {
	NOTFOUND = 0xFFFFFFFFFFFFFFFFLLU
};

class SuccinctBitVector {
private:
	const uint64_t size;    // ビットベクトルのサイズ
	static const uint64_t blockBitNum = 16;
	static const uint64_t LEVEL_L = 512;
	static const uint64_t LEVEL_S = 16;

	std::vector<uint64_t> L;   // 大ブロック
	std::vector<uint16_t> S;   // 小ブロック
	std::vector<uint16_t> B;   // ビットベクトル

	uint64_t numOne = 0;       // 1bitの数

public:
	explicit SuccinctBitVector(const uint64_t n) : size(n) {
		const uint64_t s = (n + blockBitNum - 1) / blockBitNum + 1;   // ceil(n, blockSize)
		this->B.assign(s, 0);
		this->L.assign(n / LEVEL_L + 1, 0);
		this->S.assign(n / LEVEL_S + 1, 0);
	}

	// B[pos] = bit
	void setBit(const uint64_t bit, const uint64_t pos) {
		assert(bit == 0 or bit == 1);
		assert(pos < this->size);

		const uint64_t blockPos = pos / blockBitNum;
		const uint64_t offset = pos % blockBitNum;
		if (bit == 1) { B.at(blockPos) |= (1LLU << offset); }
		else { B.at(blockPos) &= (~(1LLU << offset)); }
	}

	// B[pos]
	uint64_t access(const uint64_t pos) {
		assert(pos < this->size);
		const uint64_t blockPos = pos / blockBitNum;
		const uint64_t offset = pos % blockBitNum;
		return ((B.at(blockPos) >> offset) & 1);
	}

	void build() {
		uint64_t num = 0;
		for (uint64_t i = 0; i <= size; i++) {
			if (i % LEVEL_L == 0) {
				L.at(i / LEVEL_L) = num;
			}
			if (i % LEVEL_S == 0) {
				S.at(i / LEVEL_S) = (uint16_t)(num - L.at(i / LEVEL_L));
			}
			if (i != size and i % blockBitNum == 0) {
				num += this->popCount(this->B.at(i / blockBitNum));
			}
		}
		this->numOne = num;
	}

	// B[0, pos)のbitの数
	uint64_t rank(const uint64_t bit, const uint64_t pos) {
		assert(bit == 0 or bit == 1);
		assert(pos <= this->size);

		if (bit) {
			return L[pos / LEVEL_L] + S[pos / LEVEL_S] + popCount(B[pos / blockBitNum] & ((1 << (pos % blockBitNum)) - 1));
		}
		else {
			return pos - rank(1, pos);
		}
	}

	// rank番目のbitの位置 + 1(rankは1-origin)
	uint64_t select(const uint64_t bit, const uint64_t rank) {
		assert(bit == 0 or bit == 1);
		assert(rank > 0);
		if (bit == 0 and rank > this->size - this->numOne) { return NOTFOUND; }
		if (bit == 1 and rank > this->numOne) { return NOTFOUND; }

		// 大ブロックL内を検索
		uint64_t large_idx = 0;
		{
			uint64_t left = 0;
			uint64_t right = L.size();
			while (right - left > 1) {
				uint64_t mid = (left + right) / 2;
				uint64_t r = L.at(mid);
				r = (bit) ? r : mid * LEVEL_L - L.at(mid);

				if (r < rank) {
					left = mid;
					large_idx = mid;
				}
				else {
					right = mid;
				}
			}
		}

		// 小ブロックS内を検索
		uint64_t small_idx = (large_idx * LEVEL_L) / LEVEL_S;
		{
			uint64_t left = (large_idx * LEVEL_L) / LEVEL_S;
			uint64_t right = std::min(((large_idx + 1) * LEVEL_L) / LEVEL_S, (uint64_t)S.size());
			while (right - left > 1) {
				uint64_t mid = (left + right) / 2;
				uint64_t r = L.at(large_idx) + S.at(mid);
				r = (bit) ? r : mid * LEVEL_S - r;

				if (r < rank) {
					left = mid;
					small_idx = mid;
				}
				else {
					right = mid;
				}
			}
		}

		// Bをブロック単位で順番に探索
		uint64_t rank_pos = 0;
		{
			const uint64_t begin_block_idx = (small_idx * LEVEL_S) / blockBitNum;
			uint64_t total_bit = L.at(large_idx) + S.at(small_idx);
			if (bit == 0) {
				total_bit = small_idx * LEVEL_S - total_bit;
			}
			for (uint64_t i = 0;; ++i) {
				uint64_t b = popCount(B.at(begin_block_idx + i));
				if (bit == 0) {
					b = blockBitNum - b;
				}
				if (total_bit + b >= rank) {
					uint64_t block = (bit) ? B.at(begin_block_idx + i) : ~B.at(begin_block_idx + i);
					rank_pos = (begin_block_idx + i) * blockBitNum + selectInBlock(block, rank - total_bit);
					break;
				}
				total_bit += b;
			}
		}

		return rank_pos + 1;
	}

	uint64_t getNumOne() const {
		return numOne;
	}

	void debug() {
		std::cout << "LEVEL_L(" << L.size() << ")" << std::endl;
		for (uint64_t i = 0; i < L.size(); ++i) {
			std::cout << L.at(i) << ", ";
		}
		std::cout << std::endl;
		std::cout << "LEVEL_S(" << S.size() << ")" << std::endl;
		for (uint64_t i = 0; i < S.size(); ++i) {
			std::cout << S.at(i) << ", ";
		}
		std::cout << std::endl;
	}

private:
	uint64_t popCount(uint64_t x) {
		x = (x & 0x5555555555555555ULL) + ((x >> 1) & 0x5555555555555555ULL);
		x = (x & 0x3333333333333333ULL) + ((x >> 2) & 0x3333333333333333ULL);
		x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0fULL;
		x = x + (x >> 8);
		x = x + (x >> 16);
		x = x + (x >> 32);
		return x & 0x7FLLU;
	}

	uint64_t selectInBlock(uint64_t x, uint64_t rank) {
		uint64_t x1 = x - ((x & 0xAAAAAAAAAAAAAAAALLU) >> 1);
		uint64_t x2 = (x1 & 0x3333333333333333LLU) + ((x1 >> 2) & 0x3333333333333333LLU);
		uint64_t x3 = (x2 + (x2 >> 4)) & 0x0F0F0F0F0F0F0F0FLLU;

		uint64_t pos = 0;
		for (;; pos += 8) {
			uint64_t rank_next = (x3 >> pos) & 0xFFLLU;
			if (rank <= rank_next) break;
			rank -= rank_next;
		}

		uint64_t v2 = (x2 >> pos) & 0xFLLU;
		if (rank > v2) {
			rank -= v2;
			pos += 4;
		}

		uint64_t v1 = (x1 >> pos) & 0x3LLU;
		if (rank > v1) {
			rank -= v1;
			pos += 2;
		}

		uint64_t v0 = (x >> pos) & 0x1LLU;
		if (v0 < rank) {
			rank -= v0;
			pos += 1;
		}

		return pos;
	}
};
class WaveletMatrix {
private:
	std::vector<SuccinctBitVector> bit_arrays;
	std::vector<uint64_t> begin_one;                    // 各bitに着目したときの1の開始位置
	std::map<uint64_t, uint64_t> begin_alphabet;        // 最後のソートされた配列で各文字の開始位置
	std::vector<std::vector<uint64_t>> cumulative_sum;  // 各bitに着目したときの累積和

	uint64_t size;                                 // 与えられた配列のサイズ
	uint64_t maximum_element;                      // 文字数
	uint64_t bit_size;                             // 文字を表すのに必要なbit数

public:
	WaveletMatrix(const std::vector<uint64_t>& array) {
		assert(array.size() > 0);
		size = array.size();
		maximum_element = *max_element(array.begin(), array.end()) + 1;
		bit_size = get_num_of_bit(maximum_element);
		if (bit_size == 0) {
			bit_size = 1;
		}

		for (uint64_t i = 0; i < bit_size; ++i) {
			SuccinctBitVector sv(size);
			bit_arrays.push_back(sv);
		}
		this->begin_one.resize(bit_size);
		this->cumulative_sum.resize(bit_size + 1, std::vector<uint64_t>(size + 1, 0));

		for (uint64_t j = 0; j < array.size(); ++j) {
			this->cumulative_sum.at(0).at(j + 1) = this->cumulative_sum.at(0).at(j) + array[j];
		}

		std::vector<uint64_t> v(array);
		for (uint64_t i = 0; i < bit_size; ++i) {

			std::vector<uint64_t> temp;
			// 0をtempにいれてく
			for (uint64_t j = 0; j < v.size(); ++j) {
				uint64_t c = v.at(j);
				uint64_t bit = (c >> (bit_size - i - 1)) & 1;  //　上からi番目のbit
				if (bit == 0) {
					temp.push_back(c);
					bit_arrays.at(i).setBit(0, j);
				}
			}

			this->begin_one.at(i) = temp.size();

			// 1をtempにいれてく
			for (uint64_t j = 0; j < v.size(); ++j) {
				uint64_t c = v.at(j);
				uint64_t bit = (c >> (bit_size - i - 1)) & 1;  //　上からi番目のbit
				if (bit == 1) {
					temp.push_back(c);
					bit_arrays.at(i).setBit(1, j);
				}
			}

			for (uint64_t j = 0; j < temp.size(); ++j) {
				this->cumulative_sum.at(i + 1).at(j + 1) = this->cumulative_sum.at(i + 1).at(j) + temp.at(j);
			}

			bit_arrays.at(i).build();
			v = temp;
		}

		// ソートされた配列内での各文字の位置を取得
		for (int i = (int)v.size() - 1; i >= 0; --i) {
			this->begin_alphabet[v.at(i)] = i;
		}
	}

	// v[pos]
	uint64_t access(uint64_t pos) {
		if (pos >= this->size) { return NOTFOUND; }

		uint64_t c = 0;
		for (uint64_t i = 0; i < bit_arrays.size(); ++i) {
			uint64_t bit = bit_arrays.at(i).access(pos);   // もとの数値のi番目のbit
			c = (c <<= 1) | bit;
			pos = bit_arrays.at(i).rank(bit, pos);
			if (bit) {
				pos += this->begin_one.at(i);
			}
		}
		return c;
	}

	// i番目のcの位置 + 1を返す。rankは1-origin
	uint64_t select(uint64_t c, uint64_t rank) {
		assert(rank > 0);
		if (c >= maximum_element) {
			return NOTFOUND;
		}
		if (this->begin_alphabet.find(c) == this->begin_alphabet.end()) {
			return NOTFOUND;
		}

		uint64_t index = this->begin_alphabet.at(c) + rank;
		for (uint64_t i = 0; i < bit_arrays.size(); ++i) {
			uint64_t bit = ((c >> i) & 1);      // 下からi番目のbit
			if (bit == 1) {
				index -= this->begin_one.at(bit_size - i - 1);
			}
			index = this->bit_arrays.at(bit_size - i - 1).select(bit, index);
		}
		return index;
	}

	// v[begin_pos, end_pos)で最大値のindexを返す
	uint64_t maxRange(uint64_t begin_pos, uint64_t end_pos) {
		return quantileRange(begin_pos, end_pos, end_pos - begin_pos - 1);
	}

	// v[begin_pos, end_pos)で最小値のindexを返す
	uint64_t minRange(uint64_t begin_pos, uint64_t end_pos) {
		return quantileRange(begin_pos, end_pos, 0);
	}

	// v[begin_pos, end_pos)でk番目に小さい数値のindexを返す(kは0-origin)
	// つまり小さい順に並べてk番目の値
	uint64_t quantileRange(uint64_t begin_pos, uint64_t end_pos, uint64_t k) {
		if ((end_pos > size || begin_pos >= end_pos) || (k >= end_pos - begin_pos)) {
			return NOTFOUND;
		}

		uint64_t val = 0;
		for (uint64_t i = 0; i < bit_size; ++i) {
			const uint64_t num_of_zero_begin = bit_arrays.at(i).rank(0, begin_pos);
			const uint64_t num_of_zero_end = bit_arrays.at(i).rank(0, end_pos);
			const uint64_t num_of_zero = num_of_zero_end - num_of_zero_begin;     // beginからendまでにある0の数
			const uint64_t bit = (k < num_of_zero) ? 0 : 1;                       // k番目の値の上からi番目のbitが0か1か

			if (bit) {
				k -= num_of_zero;
				begin_pos = this->begin_one.at(i) + begin_pos - num_of_zero_begin;
				end_pos = this->begin_one.at(i) + end_pos - num_of_zero_end;
			}
			else {
				begin_pos = num_of_zero_begin;
				end_pos = num_of_zero_begin + num_of_zero;
			}

			val = ((val << 1) | bit);
		}

		uint64_t left = 0;
		for (uint64_t i = 0; i < bit_size; ++i) {
			const uint64_t bit = (val >> (bit_size - i - 1)) & 1;  // 上からi番目のbit
			left = bit_arrays.at(i).rank(bit, left);               // cのi番目のbitと同じ数値の数
			if (bit) {
				left += this->begin_one.at(i);
			}
		}

		const uint64_t rank = begin_pos + k - left + 1;
		return select(val, rank) - 1;
	}

	// v[0, pos)のcの数
	uint64_t rank(uint64_t c, uint64_t pos) {
		assert(pos < size);
		if (c >= maximum_element) {
			return 0;
		}
		if (this->begin_alphabet.find(c) == this->begin_alphabet.end()) {
			return 0;
		}

		for (uint64_t i = 0; i < bit_size; ++i) {
			uint64_t bit = (c >> (bit_size - i - 1)) & 1;  // 上からi番目のbit
			pos = bit_arrays.at(i).rank(bit, pos);         // cのi番目のbitと同じ数値の数
			if (bit) {
				pos += this->begin_one.at(i);
			}
		}

		uint64_t begin_pos = this->begin_alphabet.at(c);
		return pos - begin_pos;
	}

	// v[begin_pos, end_pos)で[min, max)に入る値の個数
	uint64_t rangeFreq(uint64_t begin_pos, uint64_t end_pos, uint64_t min_c, uint64_t max_c) {
		if ((end_pos > size || begin_pos >= end_pos) || (min_c >= max_c) || min_c >= maximum_element) {
			return 0;
		}

		const auto maxi_t = rankAll(max_c, begin_pos, end_pos);
		const auto mini_t = rankAll(min_c, begin_pos, end_pos);
		return std::get<1>(maxi_t) - std::get<1>(mini_t);
	}


	// v[begin, end)で(cと同じ値の数、cより小さい値の数、cより大きい値の数)を求める
	std::tuple<uint64_t, uint64_t, uint64_t> rankAll(const uint64_t c, uint64_t begin, uint64_t end) {
		assert(end <= size);
		const uint64_t num = end - begin;

		if (begin >= end) {
			return std::make_tuple(0, 0, 0);
		}
		if (c >= maximum_element || end == 0) {
			return std::make_tuple(0, num, 0);
		}

		uint64_t rank_less_than = 0, rank_more_than = 0;
		for (size_t i = 0; i < bit_size && begin < end; ++i) {
			const uint64_t bit = (c >> (bit_size - i - 1)) & 1;

			const uint64_t rank0_begin = this->bit_arrays.at(i).rank(0, begin);
			const uint64_t rank0_end = this->bit_arrays.at(i).rank(0, end);
			const uint64_t rank1_begin = begin - rank0_begin;
			const uint64_t rank1_end = end - rank0_end;

			if (bit) {
				rank_less_than += (rank0_end - rank0_begin);    // i番目のbitが0のものは除外される
				begin = this->begin_one.at(i) + rank1_begin;
				end = this->begin_one.at(i) + rank1_end;
			}
			else {
				rank_more_than += (rank1_end - rank1_begin);    // i番目のbitが1のものは除外される
				begin = rank0_begin;
				end = rank0_end;
			}
		}

		const uint64_t rank = num - rank_less_than - rank_more_than;
		return std::make_tuple(rank, rank_less_than, rank_more_than);
	}

private:
	uint64_t get_num_of_bit(uint64_t x) {
		if (x == 0) return 0;
		x--;
		uint64_t bit_num = 0;
		while (x >> bit_num) {
			++bit_num;
		}
		return bit_num;
	}

	uint64_t rangeSum(const uint64_t begin, const uint64_t end, const uint64_t depth, const uint64_t c, const uint64_t x, const uint64_t y) {
		if (begin == end) {
			return 0;
		}

		if (depth == bit_size) {
			if (x <= c and c < y) {
				return c * (end - begin);   // 値 * 頻度
			}
			return 0;
		}

		const uint64_t next_c = ((uint64_t)1 << (bit_size - depth - 1)) | c;                   // 上からdepth番目のbitを立てる
		const uint64_t all_one_c = (((uint64_t)1 << (bit_size - depth - 1)) - 1) | next_c;     // depth以降のbitをたてる(これ以降全部1を選んだときの値)
		if (all_one_c < x or y <= c) {
			return 0;
		}

		// [begin, pos)のすべての要素は[x, y)
		if (x <= c and all_one_c < y) {
			return this->cumulative_sum.at(depth).at(end) - this->cumulative_sum.at(depth).at(begin);
		}

		const uint64_t rank0_begin = this->bit_arrays.at(depth).rank(0, begin);
		const uint64_t rank0_end = this->bit_arrays.at(depth).rank(0, end);
		const uint64_t rank1_begin = begin - rank0_begin;
		const uint64_t rank1_end = end - rank0_end;

		return rangeSum(rank0_begin, rank0_end, depth + 1, c, x, y) +
			rangeSum(this->begin_one.at(depth) + rank1_begin, this->begin_one[depth] + rank1_end, depth + 1, next_c, x, y);
	}
};

class UniquePoint {
public:
	const int INF = 1 << 30;
	vector<pair<long long, long long>> points;
	map<long long, int> xs;
	map<long long, int> yt;
	vector<uint64_t> data;

	void add(long long y, long long x) {
		points.emplace_back(make_pair(y, x));
	}

	void build() {
		points.emplace_back(pair<ll, ll>(2ll * INF, 2ll * INF));

		// yをnew_yに変換(yは座標圧縮 2244 -> 0011)
		sort(points.begin(), points.end());  // yでソート
		int new_y = 0;
		for (int i = 0; i < points.size(); ++i) {
			const long long y = points[i].first;
			if (yt.count(y) == 0) {
				yt[y] = new_y;
				new_y++;
			}
		}

		// xをnew_wに変換(xは順位圧縮 2244 -> 0022)
		sort(points.begin(), points.end(), [&](pair<ll, ll>& a, pair<ll, ll>& b) {return a.second < b.second; }); // xでソート
		for (int i = 0; i < points.size(); ++i) {
			const long long x = points[i].second;
			if (xs.count(x) == 0) {
				xs[x] = i;
			}
		}

		data.resize(points.size());
		for (int i = 0; i < points.size(); ++i) {
			const long long y = points[i].first;
			data[i] = yt[y];
		}
	}

	pair<int, int> x2s(long long x) {
		return make_pair(xs.lower_bound(x)->second, xs.upper_bound(x)->second);
	}

	pair<int, int> y2t(long long y) {
		return make_pair(yt.lower_bound(y)->second, yt.upper_bound(y)->second);
	}
	//変換後の範囲
	tuple<int, int, int, int> grid(long long x1, long long y1, long long x2, long long y2) {
		assert(x1 <= x2);
		assert(y1 <= y2);
		return make_tuple(
			xs.lower_bound(x1)->second,
			yt.lower_bound(y1)->second,
			xs.upper_bound(x2)->second,
			yt.upper_bound(y2)->second
		);
	}

};

#ifdef ATCODER
typedef modint1000000007 mint0;
typedef modint998244353 mint;
#endif
string CONTEST = "typical90";
string PROBLEM = "typical90_cc";//問題に合わせて変える

class Answer{
public:
	char problemc;
#ifdef TESTLOCAL
	void answertest(istream& cin, ostream& cout) {

	}
#endif
	void answer(istream& cin, ostream& cout) {
		int N, M;
		cin >> N >> M;
		UniquePoint up;
		REP(i, N) {
			int x, y;
			cin >> x >> y;
			up.add(y, x);
		}
		up.build();
		WaveletMatrix wm(up.data);
		REP(i, M) {
			int x1, y1, x2, y2;
			cin >> x1 >> y1 >> x2 >> y2;
			auto g = up.grid(x1, y1, x2, y2);
			auto [nx1, ny1, nx2, ny2]=g;
			cout << (wm.rangeFreq(nx1, nx2, ny1, ny2)) << endl;
		}
	}

};

bool test(char c) {
	string inputdir = "input\\";
	string outputdir = "output\\";
	string fs = getS(inputdir + c + ".txt");
	if (fs != "") {
		string os = getS(outputdir + c + ".txt");
		ostringstream oss;
		istringstream iss(fs);
		Answer A;
		A.problemc = c;
		A.answer(iss, oss);
		if (ismatch(os, oss.str())) {
			cerr << (char)(c + 1) << ":ok" << endl;
		}
		else {
			cerr << (char)(c + 1) << ":ng" << endl;
			cerr << "true:" << endl;
			cerr << os << endl;
			cerr << "ans:" << endl;
			cerr << oss.str() << endl;
		}
		return true;
	}
	else {
		return false;
	}

}
void testall() {
	for (char c = '0'; c < '9'; c++) {
		if (!test(c))break;
	}
}
void createRandom(ostringstream& cout) {
	int N = 6;
	cout << N << endl;
	//vector<int> p = { 6,4,5,5,6,6 };
	vector<int> p = {};
	REP(i, N) {
		p.push_back((rand() % (N - i)) + i + 1);
	}
	for (auto a : p) {
		cout << a << " ";
	}
	cout << endl;
}
#ifdef TESTLOCAL
void testLocal() {
	int MAX_NUM = 100;
	int show = max(1, MAX_NUM / 10);
	REP(i, MAX_NUM) {
		ostringstream os;
		createRandom(os);
		ostringstream ostest;
		istringstream istest(os.str());
		ostringstream osa;
		istringstream isa(os.str());
		Answer At('0');
		Answer A('0');
		A.answer(isa, osa);
		At.answertest(istest, ostest);
		if (ismatch(osa.str(), ostest.str())) {
			if (i % show == 0 || i == MAX_NUM - 1) {
				cout << i << ":ok" << endl;
			}
		}
		else {
			cout << i << ":ng" << endl;
			cout << "in:" << endl;
			cout << os.str() << endl;
			cout << "true->" << endl;
			cout << ostest.str() << endl;
			cout << "false->" << endl;
			cout << osa.str() << endl;
			return;
		}
	}

}
#endif
int main() {
	cin.tie(nullptr);//出力後に必ずendl or flushすれば問題ない。
	ios::sync_with_stdio(false);//scanf printfと混ぜなければ問題ない。

#ifdef ATCODER
#ifdef _LOCAL
#ifdef TESTLOCAL
	testLocal();
#else
	if (!std::filesystem::is_regular_file(PROBLEM + "_AC")) {
		string command = "problemget.bat " + CONTEST + " " + PROBLEM;
		system(command.c_str());
	}
	testall();
#endif
#else
	Answer A;
	A.answer(cin, cout);
#endif
#else
#ifdef AIZU
#ifdef _LOCAL
	if (!std::filesystem::is_regular_file(CONTEST + "_AC")) {//問題を取得したら一旦抜ける。
		string command = "problemgetaizu.bat " + CONTEST;
		system(command.c_str());
	}
	testall();
#else
	Answer A;
	A.answer(cin, cout);
#endif
#else
	Answer A;
	A.answer(cin, cout);
#endif
#endif
#ifdef _LOCAL
	cin.get();
#endif
	return 0;
}
accuracy: 1
time_ms: 810
memory_kb: 5072
final_rank: 4

code_snippet: #pragma region Macros

#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,fma,abm,mmx,avx,avx2")

#include <bits/extc++.h>
// #include <immintrin.h>
// #include <atcoder/all>
// using namespace atcoder;
using namespace std;
using namespace __gnu_pbds;

// #include <boost/multiprecision/cpp_dec_float.hpp>
// #include <boost/multiprecision/cpp_int.hpp>
// namespace mp = boost::multiprecision;
// using Bint = mp::cpp_int;
// using Bdouble = mp::number<mp::cpp_dec_float<256>>;

#define pb emplace_back
#define int ll
#define endl '\n'

#define sqrt __builtin_sqrt
#define cbrt __builtin_cbrt
#define hypot __builtin_hypot

using ll = long long;
using ld = long double;
const ld PI = acosl(-1);
const int INF = 1 << 30;
const ll INFL = 1LL << 61;
const int MOD = 998244353;
// const int MOD = 1000000007;

const ld EPS = 1e-10;
const bool equals(ld a, ld b) { return fabs((a) - (b)) < EPS; }

const vector<int> dx = {0, 1, 0, -1, 1, 1, -1, -1}; // → ↓ ← ↑ ↘ ↙ ↖ ↗
const vector<int> dy = {1, 0, -1, 0, 1, -1, -1, 1};

struct Edge {
    int from, to;
    ll cost;
    Edge(int to, ll cost) : to(to), cost(cost) {}
    Edge(int from, int to, ll cost) : from(from), to(to), cost(cost) {}
};

chrono::system_clock::time_point  start, now;
__attribute__((constructor))
void constructor() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(10);
    start = chrono::system_clock::now();
}

__int128_t POW(__int128_t x, int n) {
    __int128_t ret = 1;
    assert(n >= 0);
    if (x == 1 or n == 0) ret = 1;
    else if (x == -1 && n % 2 == 0) ret = 1; 
    else if (x == -1) ret = -1; 
    else if (n % 2 == 0) {
        assert(x < INFL);
        ret = POW(x * x, n / 2);
    } else {
        assert(x < INFL);
        ret = x * POW(x, n - 1);
    }
    return ret;
}
int per(int x, int y) { // x = qy + r (0 <= r < y) を満たすq
    assert(y != 0);
    if (x >= 0 && y > 0) return x / y;
    if (x >= 0 && y < 0) return x / y - (x % y < 0);
    if (x < 0 && y < 0) return x / y + (x % y < 0);
    return x / y - (x % y < 0); //  (x < 0 && y > 0) 
}
// int perl(ld x, ld y) { // perld(4.5, 2.1) = 2  // TODO
//     if (-EPS < x && x < 0 or 0 < x && x < EPS) x = 0;
//     if (-EPS < y && y < 0 or 0 < x && x < EPS) y = 0;
//     assert(!equals(y, 0));
//     if (x >= 0 && y > 0) return floor(x / y)+EPS;
//     if (x >= 0 && y < 0) return floor(x / y) - (x - floor(x/y)*y < -EPS);
//     if (x < 0 && y < 0) return floor(x / y) + (x - floor(x/y)*y < -EPS);
//     return floor(x / y) - (x - floor(x/y)*y < -EPS); //  (x < 0 && y > 0) 
// }
int mod(int x, int y) { // x = qy + r (0 <= r < y) を満たすr
    assert(y != 0);
    if (x >= 0) return x % y;
    __int128_t ret = x % y; // (x < 0)
    ret += (__int128_t)abs(y) * INFL;
    ret %= abs(y);
    return ret;
}
// ld modl(ld x, ld y) { // TODO
//     assert(!equals(y, 0));
//     if (x >= -EPS) return (x - floor(x/y)*y);
//     ld ret = x - floor(x/y)*y; // (x < 0)
//     ret += abs(y) * INFL; // TODO : オーバーフローする?
//     ret = x - floor(x/abs(y))*abs(y);
//     return ret;
// }
// int floor(int x, int y) { // TODO
//     assert(y != 0);
//     if (b < 0) a = -a, b = -b;
//     return a >= 0 ? a / b : (a + 1) / b - 1;
// }
// int ceil(int x, int y) { // TODO
// assert(y != 0);
//     if (b < 0) a = -a, b = -b;
//     return a > 0 ? (a - 1) / b + 1 : a / b;
// }
// int floorl(ld x, ld y) { return 0; } // TODO
// int ceill(ld x, ld y) { return 0; } // TODO
// int gauss(int x, int y) {
//     assert(y != 0);
//     return x / y;
// } // 整数部分(未verify)
// int gauss(ld x, ld y) { return 0; } // TODO

pair<int, int> max(const pair<int, int> &a, const pair<int, int> &b) {
    if (a.first > b.first or a.first == b.first && a.second > b.second) {
        return a;
    }
    return b;
}
pair<int, int> min(const pair<int, int> &a, const pair<int, int> &b) {
    if (a.first < b.first or a.first == b.first && a.second < b.second) {
        return a;
    }
    return b;
}

template <class T> bool chmax(T &a, const T& b) {
    if (a < b) { a = b; return true; }
    return false;
}
template <class T> bool chmin(T &a, const T& b) {
    if (a > b) { a = b; return true; }
    return false;
}
template <class T> T mid(T a, T b, T c) {
    return a + b + c - max({a, b, c}) - min({a, b, c});
}
template <class T> void sort(T &a, T &b, T &c, bool rev = false) {
    if (rev == false) { 
        if (a > b) swap(a, b);
        if (a > c) swap(a, c);
        if (b > c) swap(b, c);
    } else {
        if (c > b) swap(c, b);
        if (c > a) swap(c, a);
        if (b > a) swap(b, a);
    }
}
template <class T> void sort(T &a, T &b, T &c, T &d, bool rev = false) {
    if (rev == false) { 
        if (a > b) swap(a, b); if (a > c) swap(a, c);  if (a > d) swap(a, d);
        if (b > c) swap(b, c); if (b > d) swap(b, d);
        if (c > d) swap(c, d);
    } else {
        if (d > c) swap(d, c); if (d > b) swap(d, b); if (d > a) swap(d, a);
        if (c > b) swap(c, b); if (c > a) swap(c, a);
        if (b > a) swap(b, a);
    }
}

int countl_zero(int x) { return __builtin_clzll(x); }
int countl_one(int x) {
    int ret = 0; while (x % 2) { x /= 2; ret++; }
    return ret;
}
int countr_zero(int x) { return __builtin_ctzll(x); }
int countr_one(int x) {
    int ret = 0, k = 63 - __builtin_clzll(x);
    while (k != -1 && (x & (1LL << k))) { k--; ret++; }
    return ret;
}
int popcount(int x) { return __builtin_popcountll(x); }
int unpopcount(int x) { return 64 - __builtin_clzll(x) - __builtin_popcountll(x); }

int top_bit(int x) { return 63 - __builtin_clzll(x);} // 2^kの位
int bot_bit(int x) { return __builtin_ctz(x);} // 2^kの位
int MSB(int x) { return 1 << (63 - __builtin_clzll(x)); } // mask
int LSB(int x) { return (x & -x); } // mask

int bit_width(int x) { return 64 - __builtin_clzll(x); } // 桁数
int ceil_log2(int x) { return 63 - __builtin_clzll(x); }
int bit_floor(int x) { return 1 << (63 - __builtin_clzll(x)); }
int floor_log2(int x) { return 64 - __builtin_clzll(x-1); }
int bit_ceil(int x) { return 1 << (64 - __builtin_clzll(x-1)) - (x==1); }

int hamming(int a, int b) { return popcount(a ^ b); }
int compcnt(int x) { return (popcount(x^(x >> 1)) + (x&1)) / 2; }

class UnionFind {
public:
	UnionFind() = default;
    UnionFind(int N) : par(N), sz(N, 1) {
        iota(par.begin(), par.end(), 0);
    }

	int root(int x) {
		if (par[x] == x) return x;
		return (par[x] = root(par[x]));
	}

	bool unite(int x, int y) {
		int rx = root(x);
		int ry = root(y);

        if (rx == ry) return false;
		if (sz[rx] < sz[ry]) swap(rx, ry);

		sz[rx] += sz[ry];
		par[ry] = rx;

        return true;
	}

	bool issame(int x, int y) { return (root(x) == root(y)); }
	int size(int x) { return sz[root(x)]; }

    vector<vector<int>> groups(int N) {
        vector<vector<int>> G(N);
        for (int x = 0; x < N; x++) {
            G[root(x)].push_back(x);
        }
		G.erase(
            remove_if(G.begin(), G.end(),
                [&](const vector<int>& V) { return V.empty(); }),
                    G.end());
        return G;
    }
private:
	vector<int> par;
	vector<int> sz;
};

template<int mod> class Modint{
public:
    int val = 0;
    Modint(int x = 0) { while (x < 0) x += mod; val = x % mod; }
    Modint(const Modint &r) { val = r.val; }

    Modint operator -() { return Modint(-val); } // 単項
    Modint operator +(const Modint &r) { return Modint(*this) += r; }
    Modint operator +(const int &q) { Modint r(q); return Modint(*this) += r; }
    Modint operator -(const Modint &r) { return Modint(*this) -= r; }
    Modint operator -(const int &q) { Modint r(q); return Modint(*this) -= r; }
    Modint operator *(const Modint &r) { return Modint(*this) *= r; }
    Modint operator *(const int &q) { Modint r(q); return Modint(*this) *= r; }
    Modint operator /(const Modint &r) { return Modint(*this) /= r; }
    Modint operator /(const int &q) { Modint r(q); return Modint(*this) /= r; }
    
    Modint& operator ++() { val++; if (val >= mod) val -= mod; return *this; } // 前置
    Modint operator ++(signed) { ++*this; return *this; } // 後置
    Modint& operator --() { val--; if (val < 0) val += mod; return *this; }
    Modint operator --(signed) { --*this; return *this; }
    Modint &operator +=(const Modint &r) { val += r.val; if (val >= mod) val -= mod; return *this; }
    Modint &operator +=(const int &q) { Modint r(q); val += r.val; if (val >= mod) val -= mod; return *this; }
    Modint &operator -=(const Modint &r) { if (val < r.val) val += mod; val -= r.val; return *this; }
    Modint &operator -=(const int &q) { Modint r(q);  if (val < r.val) val += mod; val -= r.val; return *this; }
    Modint &operator *=(const Modint &r) { val = val * r.val % mod; return *this; }
    Modint &operator *=(const int &q) { Modint r(q); val = val * r.val % mod; return *this; }
    Modint &operator /=(const Modint &r) {
        int a = r.val, b = mod, u = 1, v = 0;
        while (b) {int t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v);}
        val = val * u % mod; if (val < 0) val += mod;
        return *this;
    }
    Modint &operator /=(const int &q) {
        Modint r(q); int a = r.val, b = mod, u = 1, v = 0;
        while (b) {int t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v);}
        val = val * u % mod; if (val < 0) val += mod;
        return *this;
    }

    bool operator ==(const Modint& r) { return this -> val == r.val; }
    bool operator <(const Modint& r) { return this -> val < r.val; }
    bool operator >(const Modint& r) { return this -> val > r.val; }
    bool operator !=(const Modint& r) { return this -> val != r.val; }
};

using mint = Modint<MOD>;
// using Mint = modint998244353;

istream &operator >>(istream &is, mint& x) {
    int t; is >> t;
    x = t;
    return (is);
}
ostream &operator <<(ostream &os, const mint& x) {
    return os << x.val;
}
mint modpow(const mint &x, int n) {
    assert(n >= 0); // TODO: n <= -1
    if (n == 0) return 1;
    mint t = modpow(x, n / 2);
    t = t * t;
    if (n & 1) t = t * x;
    return t;
}

int modpow(__int128_t x, int n, int mod) {
    assert(n >= 0 && mod > 0); // TODO: n <= -1
    __int128_t ret = 1;
    while (n > 0) {
        if (n % 2 == 1) ret = ret * x % mod;
        x = x * x % mod;
        n /= 2;
    }
    return ret;
}

int modinv(__int128_t x, int mod) {
    assert(mod > 0 && x > 0);
    if (x == 1) return 1;
    return mod - modinv(mod % x, mod) * (mod / x) % mod;
}

istream &operator >>(istream &is, __int128_t& x) {
    string S; is >> S;
    __int128_t ret = 0;
    int f = 1;
    if (S[0] == '-') f = -1; 
    for (int i = 0; i < S.length(); i++)
        if ('0' <= S[i] && S[i] <= '9')
            ret = ret * 10 + S[i] - '0';
    x = ret * f;
    return (is);
}
ostream &operator <<(ostream &os, __int128_t x) {
    ostream::sentry s(os);
    if (s) {
        __uint128_t tmp = x < 0 ? -x : x;
        char buffer[128];
        char *d = end(buffer);

        do {
            --d;
            *d = "0123456789"[tmp % 10];
            tmp /= 10;
        } while (tmp != 0);

        if (x < 0) {
            --d;
            *d = '-';
        }
        int len = end(buffer) - d;

        if (os.rdbuf()->sputn(d, len) != len) {
            os.setstate(ios_base::badbit);
        }
    }
    return os;
}

__int128_t stoll(string &S) {
    __int128_t ret = 0;
    int f = 1;
    if (S[0] == '-') f = -1; 
    for (int i = 0; i < S.length(); i++)
        if ('0' <= S[i] && S[i] <= '9')
            ret = ret * 10 + S[i] - '0';
    return ret * f;
}
__int128_t gcd(__int128_t a, __int128_t b) {
    return b ? gcd(b, a % b) : a;
}
__int128_t lcm(__int128_t a, __int128_t b) {
    return a / gcd(a, b) * b;
    // lcmが__int128_tに収まる必要あり
}

string to_string(ld x, int k) { // xの小数第k位までをstring化する
    assert(k >= 0);
    stringstream ss;
    ss << setprecision(k + 2) << x;
    string s = ss.str();
    if (s.find('.') == string::npos) s += '.';
    int pos = s.find('.');
    for (int i = 0; k >= (int)s.size() - 1 - pos; i++) s += '0';
    s.pop_back();
    if (s.back() == '.') s.pop_back();
    return s;

    // stringstream ss; // 第k+1位を四捨五入して第k位まで返す
    // ss << setprecision(k + 1) << x;
    // string s = ss.str();
    // if (s.find('.') == string::npos) s += '.';
    // int pos = s.find('.');
    // for (int i = 0; k > (int)s.size() - 1 - pos; i++) s += '0';
    // if (s.back() == '.') s.pop_back();
    // return s;
}

string to_string(__int128_t x) {
    string ret = "";
    if (x < 0) {
        ret += "-";
        x *= -1;
    }
    while (x) {
        ret += (char)('0' + x % 10);
        x /= 10;
    }
    reverse(ret.begin(), ret.end());
    return ret;
}
string to_string(char c) {
    string s = "";
    s += c;
    return s;
}

struct SXor128 {
    uint64_t x = 88172645463325252LL;
    unsigned Int() {
        x = x ^ (x << 7);
        return x = x ^ (x >> 9);
    }
    unsigned Int(unsigned mod) {
        x = x ^ (x << 7);
        x = x ^ (x >> 9);
        return x % mod;
    }
    unsigned Int(unsigned l, unsigned r) {
        x = x ^ (x << 7);
        x = x ^ (x >> 9);
        return x % (r - l + 1) + l;
    }
    double Double() {
        return double(Int()) / UINT_MAX;
    }
} rnd;

struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};

template<class T> size_t HashCombine(const size_t seed,const T &v){
    return seed^(hash<T>()(v)+0x9e3779b9+(seed<<6)+(seed>>2));
}
template<class T,class S> struct hash<pair<T,S>>{
    size_t operator()(const pair<T,S> &keyval) const noexcept {
        return HashCombine(hash<T>()(keyval.first), keyval.second);
    }
};
template<class T> struct hash<vector<T>>{
    size_t operator()(const vector<T> &keyval) const noexcept {
        size_t s=0;
        for (auto&& v: keyval) s=HashCombine(s,v);
        return s;
    }
};
template<int N> struct HashTupleCore{
    template<class Tuple> size_t operator()(const Tuple &keyval) const noexcept{
        size_t s=HashTupleCore<N-1>()(keyval);
        return HashCombine(s,get<N-1>(keyval));
    }
};
template <> struct HashTupleCore<0>{
    template<class Tuple> size_t operator()(const Tuple &keyval) const noexcept{ return 0; }
};
template<class... Args> struct hash<tuple<Args...>>{
    size_t operator()(const tuple<Args...> &keyval) const noexcept {
        return HashTupleCore<tuple_size<tuple<Args...>>::value>()(keyval);
    }
};

vector<mint> _fac, _finv, _inv;
void COMinit(int N) {
    _fac.resize(N + 1);
    _finv.resize(N + 1);
    _inv.resize(N + 1);
    _fac[0] = _fac[1] = 1;
    _finv[0] = _finv[1] = 1;
    _inv[1] = 1;
    for (int i = 2; i <= N; i++) {
        _fac[i] = _fac[i-1] * mint(i);
        _inv[i] = -_inv[MOD % i] * mint(MOD / i);
        _finv[i] = _finv[i - 1] * _inv[i];
    }
}

mint FAC(int N) {
    if (N < 0) return 0;
    return _fac[N];
}
mint COM(int N, int K) {
    if (N < K) return 0;
    if (N < 0 or K < 0) return 0;
    return _fac[N] * _finv[K] * _finv[N - K];
}
mint PERM(int N, int K) {
    if (N < K) return 0;
    if (N < 0 or K < 0) return 0;
    return _fac[N] *  _finv[N - K];
}
mint NHK(int N, int K) {
    if (N == 0 && K == 0)  return 1;
    return COM(N + K - 1, K);
}

#pragma endregion

struct Bit_Vector {
    int n, m;
    vector<uint64_t> bit;
    vector<int> sum;

    Bit_Vector(int n) : n(n), m((n + 63) / 64), bit(m), sum(m + 1) {}
    void set(int k) { bit[k / 64] |= 1ULL << (k % 64); }
    void build() {
        for (int i = 0; i < m; i++) {
            sum[i + 1] = sum[i] + __builtin_popcountll(bit[i]);
        }
    }
    bool operator[](int k) const { return (bit[k / 64] >> (k % 64)) & 1ULL; }
   
    int rank(int r, bool b) const {
        int one = sum[r / 64];
        if (r & 63) one += __builtin_popcountll(bit[r / 64] & ((1ULL << (r % 64)) - 1));
        return b ? one : r - one;
    }
    
    int rank(int l, int r, bool b) const { return rank(r, b) - rank(l, b); }
};

template<typename T>
struct WaveletMatrix {
    int maxlog, n;
    vector<Bit_Vector> matrix;
    vector<int> zero_cnt;
    vector<vector<ll>> cs;

    WaveletMatrix(vector<T> data, ll max_v) : n(data.size()) {
        T min_v = n ? *min_element(data.begin(), data.end()) : 0;
        assert(0 <= min_v);
        maxlog = max(64 - __builtin_clzll(max_v), 1);
        matrix.resize(maxlog, Bit_Vector(n));
        cs.resize(maxlog, vector<ll>(n + 1));
        zero_cnt.resize(maxlog);
        vector<T> zero(n), one(n);

        for (int i = 0; i < maxlog; i++) {
            int z = 0, o = 0;
            for (int j = 0; j < n; j++) {
                if ((data[j] >> (maxlog - 1 - i)) & 1) {
                    one[o++] = data[j];
                    matrix[i].set(j);
                } 
                else {
                    zero[z++] = data[j];
                    zero_cnt[i]++;
                }
            }
            matrix[i].build();
            data.swap(zero);
            for (int i = 0; i < o; i++) data[z + i] = one[i];
            for (int j = 0; j < n; j++) cs[i][j + 1] = cs[i][j] + data[j];
        }
    }

    T access(int k) {
        T ret = 0;
        for (int i = 0; i < maxlog; i++) {
            bool bit = matrix[i][k];
            ret = (ret << 1) | bit;
            k = matrix[i].rank(k, bit) + zero_cnt[i] * bit;
        }
        return ret;
    }

    int rank(int l, int r, T x) {
        for (int i = 0; i < maxlog; i++) {
            bool bit = (x >> (maxlog - 1 - i)) & 1;
            l = matrix[i].rank(l, bit) + zero_cnt[i] * bit;
            r = matrix[i].rank(r, bit) + zero_cnt[i] * bit;
        }
        return r - l;
    }
   
    T kth_smallest(int l, int r, int k) const {
        assert(0 <= k && k < r - l);
        T res = 0;
        for (int i = 0; i < maxlog; i++) {
            int zero = matrix[i].rank(l, r, 0);
            bool bit = k >= zero;
            l = matrix[i].rank(l, bit) + zero_cnt[i] * bit;
            r = matrix[i].rank(r, bit) + zero_cnt[i] * bit;
            res |= (T(1) << (maxlog - 1 - i)) * bit;
            k -= zero * bit;
        }
        return res;
    }

    T kth_largest(int l, int r, int k) { kth_smallest(l, r, r - l - k - 1); }

    tuple<int, int, int> rank_all(int l, int r, T x) const {
        int lt_cnt = 0, eq_cnt = r - l , mt_cnt = 0;
        for (int i = 0; i < maxlog; i++) {
            int tmp = r - l;
            bool bit = (x >> (maxlog - 1 - i)) & 1;
            l = matrix[i].rank(l, bit) + zero_cnt[i] * bit;
            r = matrix[i].rank(r, bit) + zero_cnt[i] * bit;
            int d = tmp - (r - l);
            eq_cnt -= d;
            (bit ? lt_cnt : mt_cnt) += d;
        }
        return { lt_cnt, eq_cnt, mt_cnt };
    }

    int range_freq(int l, int r, T lower, T upper) {
        auto l_cnt = get<0>(rank_all(l, r, lower));
        auto r_cnt = get<0>(rank_all(l, r, upper));
        return r_cnt - l_cnt;        
    }

    T prev_value(int l, int r, T upper) {
        int cnt = get<0>(rank_all(l, r, upper));
        return cnt == 0 ? T(-1) : kth_smallest(l, r, --cnt);
    } 

    T next_value(int l, int r, T lower) {
        int cnt = get<0>(rank_all(l, r, lower));
        return cnt == r - l ? T(-1) : kth_smallest(l, r, cnt);
    }

    ll sum_less_than(int l, int r, T x) {
        ll ret = 0;
        for (int i = 0; i < maxlog; i++) {
            bool bit = (x >> (maxlog - 1 - i) & 1);
            if (bit) ret += cs[i][matrix[i].rank(r, 0)] - cs[i][matrix[i].rank(l, 0)];
            l = matrix[i].rank(l, bit) + zero_cnt[i] * bit;
            r = matrix[i].rank(r, bit) + zero_cnt[i] * bit;
        }
        return ret;
    }

    ll range_sum(int l, int r, T lower, T upper) { 
        return sum_less_than(l, r, upper) - sum_less_than(l, r, lower);
    }
};

class UniquePoint {
public:
    vector<pair<int, int>> P;
    map<int, int> xs;
    vector<int> data;

    UniquePoint() {}

    void insert(int x, int y) {
        P.pb(make_pair(x, y));
    }

    void unique() {
        P.pb(make_pair(INFL, INFL));

        // xをuniqueになるように変換
        sort(P.begin(), P.end(),
            [&](pair<int, int> &a, pair<int, int> &b) {
                return a.first < b.first;
            }); // xでソート

        for (int i = 0; i < P.size(); i++) {
            const int x = P[i].first;
            if (xs.count(x) == 0) {
                xs[x] = i;
            }
        }

        data.resize(P.size());
        for (int i = 0; i < P.size(); i++) {
            const int y = P[i].second;
            data[i] = y;
        }
    }

    pair<int, int> x2s(int x) {
        return make_pair(xs.lower_bound(x)->second, xs.upper_bound(x)->second);
    }

    // [l, r] クエリの l, r をWMのindexとして渡せる値に直す
    pair<int, int> encode(int l, int r) {
        assert(l <= r);
        return make_pair(
            xs.lower_bound(l)->second,
            xs.upper_bound(r)->second
        );
    }
};

signed main() {
	int N, Q;
    cin >> N >> Q;

    UniquePoint P;
    vector<int> X(N), Y(N);
    for (int i = 0; i < N; i++) {
        cin >> X[i] >> Y[i];
        Y[i] += 1e9+EPS;
        P.insert(X[i], Y[i]);
    }

    P.unique();

    WaveletMatrix<int> WM(P.data, 2e9 + 1);

    for (int i = 0; i < Q; i++) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        y1 += 1e9+EPS;
        y2 += 1e9+EPS;
        pair<int, int> range = P.encode(x1, x2); // [l, r) の半開区間
        // cout << range.first << " " << range.second << " " << y1 << " " << y2 << endl;
        cout << WM.range_freq(range.first, range.second, y1, y2 + 1) << endl;
    }
}
accuracy: 1
time_ms: 440
memory_kb: 5144
final_rank: 1

code_snippet: #pragma region Macros

#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,fma,abm,mmx,avx,avx2")

#include <bits/extc++.h>
// #include <immintrin.h>
// #include <atcoder/all>
// using namespace atcoder;
using namespace std;
using namespace __gnu_pbds;

// #include <boost/multiprecision/cpp_dec_float.hpp>
// #include <boost/multiprecision/cpp_int.hpp>
// namespace mp = boost::multiprecision;
// using Bint = mp::cpp_int;
// using Bdouble = mp::number<mp::cpp_dec_float<256>>;

#define pb emplace_back
// #define int ll
#define endl '\n'

#define sqrt __builtin_sqrt
#define cbrt __builtin_cbrt
#define hypot __builtin_hypot

using ll = long long;
using ld = long double;
const ld PI = acosl(-1);
const int INF = 1 << 30;
const ll INFL = 1LL << 61;
const int MOD = 998244353;
// const int MOD = 1000000007;

const ld EPS = 1e-10;
const bool equals(ld a, ld b) { return fabs((a) - (b)) < EPS; }

const vector<int> dx = {0, 1, 0, -1, 1, 1, -1, -1}; // → ↓ ← ↑ ↘ ↙ ↖ ↗
const vector<int> dy = {1, 0, -1, 0, 1, -1, -1, 1};

struct Edge {
    int from, to;
    ll cost;
    Edge(int to, ll cost) : to(to), cost(cost) {}
    Edge(int from, int to, ll cost) : from(from), to(to), cost(cost) {}
};

chrono::system_clock::time_point  start, now;
__attribute__((constructor))
void constructor() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(10);
    start = chrono::system_clock::now();
}

__int128_t POW(__int128_t x, int n) {
    __int128_t ret = 1;
    assert(n >= 0);
    if (x == 1 or n == 0) ret = 1;
    else if (x == -1 && n % 2 == 0) ret = 1; 
    else if (x == -1) ret = -1; 
    else if (n % 2 == 0) {
        assert(x < INFL);
        ret = POW(x * x, n / 2);
    } else {
        assert(x < INFL);
        ret = x * POW(x, n - 1);
    }
    return ret;
}
int per(int x, int y) { // x = qy + r (0 <= r < y) を満たすq
    assert(y != 0);
    if (x >= 0 && y > 0) return x / y;
    if (x >= 0 && y < 0) return x / y - (x % y < 0);
    if (x < 0 && y < 0) return x / y + (x % y < 0);
    return x / y - (x % y < 0); //  (x < 0 && y > 0) 
}
// int perl(ld x, ld y) { // perld(4.5, 2.1) = 2  // TODO
//     if (-EPS < x && x < 0 or 0 < x && x < EPS) x = 0;
//     if (-EPS < y && y < 0 or 0 < x && x < EPS) y = 0;
//     assert(!equals(y, 0));
//     if (x >= 0 && y > 0) return floor(x / y)+EPS;
//     if (x >= 0 && y < 0) return floor(x / y) - (x - floor(x/y)*y < -EPS);
//     if (x < 0 && y < 0) return floor(x / y) + (x - floor(x/y)*y < -EPS);
//     return floor(x / y) - (x - floor(x/y)*y < -EPS); //  (x < 0 && y > 0) 
// }
int mod(int x, int y) { // x = qy + r (0 <= r < y) を満たすr
    assert(y != 0);
    if (x >= 0) return x % y;
    __int128_t ret = x % y; // (x < 0)
    ret += (__int128_t)abs(y) * INFL;
    ret %= abs(y);
    return ret;
}
// ld modl(ld x, ld y) { // TODO
//     assert(!equals(y, 0));
//     if (x >= -EPS) return (x - floor(x/y)*y);
//     ld ret = x - floor(x/y)*y; // (x < 0)
//     ret += abs(y) * INFL; // TODO : オーバーフローする?
//     ret = x - floor(x/abs(y))*abs(y);
//     return ret;
// }
// int floor(int x, int y) { // TODO
//     assert(y != 0);
//     if (b < 0) a = -a, b = -b;
//     return a >= 0 ? a / b : (a + 1) / b - 1;
// }
// int ceil(int x, int y) { // TODO
// assert(y != 0);
//     if (b < 0) a = -a, b = -b;
//     return a > 0 ? (a - 1) / b + 1 : a / b;
// }
// int floorl(ld x, ld y) { return 0; } // TODO
// int ceill(ld x, ld y) { return 0; } // TODO
// int gauss(int x, int y) {
//     assert(y != 0);
//     return x / y;
// } // 整数部分(未verify)
// int gauss(ld x, ld y) { return 0; } // TODO

pair<int, int> max(const pair<int, int> &a, const pair<int, int> &b) {
    if (a.first > b.first or a.first == b.first && a.second > b.second) {
        return a;
    }
    return b;
}
pair<int, int> min(const pair<int, int> &a, const pair<int, int> &b) {
    if (a.first < b.first or a.first == b.first && a.second < b.second) {
        return a;
    }
    return b;
}

template <class T> bool chmax(T &a, const T& b) {
    if (a < b) { a = b; return true; }
    return false;
}
template <class T> bool chmin(T &a, const T& b) {
    if (a > b) { a = b; return true; }
    return false;
}
template <class T> T mid(T a, T b, T c) {
    return a + b + c - max({a, b, c}) - min({a, b, c});
}
template <class T> void sort(T &a, T &b, T &c, bool rev = false) {
    if (rev == false) { 
        if (a > b) swap(a, b);
        if (a > c) swap(a, c);
        if (b > c) swap(b, c);
    } else {
        if (c > b) swap(c, b);
        if (c > a) swap(c, a);
        if (b > a) swap(b, a);
    }
}
template <class T> void sort(T &a, T &b, T &c, T &d, bool rev = false) {
    if (rev == false) { 
        if (a > b) swap(a, b); if (a > c) swap(a, c);  if (a > d) swap(a, d);
        if (b > c) swap(b, c); if (b > d) swap(b, d);
        if (c > d) swap(c, d);
    } else {
        if (d > c) swap(d, c); if (d > b) swap(d, b); if (d > a) swap(d, a);
        if (c > b) swap(c, b); if (c > a) swap(c, a);
        if (b > a) swap(b, a);
    }
}

int countl_zero(int x) { return __builtin_clzll(x); }
int countl_one(int x) {
    int ret = 0; while (x % 2) { x /= 2; ret++; }
    return ret;
}
int countr_zero(int x) { return __builtin_ctzll(x); }
int countr_one(int x) {
    int ret = 0, k = 63 - __builtin_clzll(x);
    while (k != -1 && (x & (1LL << k))) { k--; ret++; }
    return ret;
}
int popcount(int x) { return __builtin_popcountll(x); }
int unpopcount(int x) { return 64 - __builtin_clzll(x) - __builtin_popcountll(x); }

int top_bit(int x) { return 63 - __builtin_clzll(x);} // 2^kの位
int bot_bit(int x) { return __builtin_ctz(x);} // 2^kの位
int MSB(int x) { return 1 << (63 - __builtin_clzll(x)); } // mask
int LSB(int x) { return (x & -x); } // mask

int bit_width(int x) { return 64 - __builtin_clzll(x); } // 桁数
int ceil_log2(int x) { return 63 - __builtin_clzll(x); }
int bit_floor(int x) { return 1 << (63 - __builtin_clzll(x)); }
int floor_log2(int x) { return 64 - __builtin_clzll(x-1); }
int bit_ceil(int x) { return 1 << (64 - __builtin_clzll(x-1)) - (x==1); }

int hamming(int a, int b) { return popcount(a ^ b); }
int compcnt(int x) { return (popcount(x^(x >> 1)) + (x&1)) / 2; }

class UnionFind {
public:
	UnionFind() = default;
    UnionFind(int N) : par(N), sz(N, 1) {
        iota(par.begin(), par.end(), 0);
    }

	int root(int x) {
		if (par[x] == x) return x;
		return (par[x] = root(par[x]));
	}

	bool unite(int x, int y) {
		int rx = root(x);
		int ry = root(y);

        if (rx == ry) return false;
		if (sz[rx] < sz[ry]) swap(rx, ry);

		sz[rx] += sz[ry];
		par[ry] = rx;

        return true;
	}

	bool issame(int x, int y) { return (root(x) == root(y)); }
	int size(int x) { return sz[root(x)]; }

    vector<vector<int>> groups(int N) {
        vector<vector<int>> G(N);
        for (int x = 0; x < N; x++) {
            G[root(x)].push_back(x);
        }
		G.erase(
            remove_if(G.begin(), G.end(),
                [&](const vector<int>& V) { return V.empty(); }),
                    G.end());
        return G;
    }
private:
	vector<int> par;
	vector<int> sz;
};

template<int mod> class Modint{
public:
    int val = 0;
    Modint(int x = 0) { while (x < 0) x += mod; val = x % mod; }
    Modint(const Modint &r) { val = r.val; }

    Modint operator -() { return Modint(-val); } // 単項
    Modint operator +(const Modint &r) { return Modint(*this) += r; }
    Modint operator +(const int &q) { Modint r(q); return Modint(*this) += r; }
    Modint operator -(const Modint &r) { return Modint(*this) -= r; }
    Modint operator -(const int &q) { Modint r(q); return Modint(*this) -= r; }
    Modint operator *(const Modint &r) { return Modint(*this) *= r; }
    Modint operator *(const int &q) { Modint r(q); return Modint(*this) *= r; }
    Modint operator /(const Modint &r) { return Modint(*this) /= r; }
    Modint operator /(const int &q) { Modint r(q); return Modint(*this) /= r; }
    
    Modint& operator ++() { val++; if (val >= mod) val -= mod; return *this; } // 前置
    Modint operator ++(signed) { ++*this; return *this; } // 後置
    Modint& operator --() { val--; if (val < 0) val += mod; return *this; }
    Modint operator --(signed) { --*this; return *this; }
    Modint &operator +=(const Modint &r) { val += r.val; if (val >= mod) val -= mod; return *this; }
    Modint &operator +=(const int &q) { Modint r(q); val += r.val; if (val >= mod) val -= mod; return *this; }
    Modint &operator -=(const Modint &r) { if (val < r.val) val += mod; val -= r.val; return *this; }
    Modint &operator -=(const int &q) { Modint r(q);  if (val < r.val) val += mod; val -= r.val; return *this; }
    Modint &operator *=(const Modint &r) { val = val * r.val % mod; return *this; }
    Modint &operator *=(const int &q) { Modint r(q); val = val * r.val % mod; return *this; }
    Modint &operator /=(const Modint &r) {
        int a = r.val, b = mod, u = 1, v = 0;
        while (b) {int t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v);}
        val = val * u % mod; if (val < 0) val += mod;
        return *this;
    }
    Modint &operator /=(const int &q) {
        Modint r(q); int a = r.val, b = mod, u = 1, v = 0;
        while (b) {int t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v);}
        val = val * u % mod; if (val < 0) val += mod;
        return *this;
    }

    bool operator ==(const Modint& r) { return this -> val == r.val; }
    bool operator <(const Modint& r) { return this -> val < r.val; }
    bool operator >(const Modint& r) { return this -> val > r.val; }
    bool operator !=(const Modint& r) { return this -> val != r.val; }
};

using mint = Modint<MOD>;
// using Mint = modint998244353;

istream &operator >>(istream &is, mint& x) {
    int t; is >> t;
    x = t;
    return (is);
}
ostream &operator <<(ostream &os, const mint& x) {
    return os << x.val;
}
mint modpow(const mint &x, int n) {
    assert(n >= 0); // TODO: n <= -1
    if (n == 0) return 1;
    mint t = modpow(x, n / 2);
    t = t * t;
    if (n & 1) t = t * x;
    return t;
}

int modpow(__int128_t x, int n, int mod) {
    assert(n >= 0 && mod > 0); // TODO: n <= -1
    __int128_t ret = 1;
    while (n > 0) {
        if (n % 2 == 1) ret = ret * x % mod;
        x = x * x % mod;
        n /= 2;
    }
    return ret;
}

int modinv(__int128_t x, int mod) {
    assert(mod > 0 && x > 0);
    if (x == 1) return 1;
    return mod - modinv(mod % x, mod) * (mod / x) % mod;
}

istream &operator >>(istream &is, __int128_t& x) {
    string S; is >> S;
    __int128_t ret = 0;
    int f = 1;
    if (S[0] == '-') f = -1; 
    for (int i = 0; i < S.length(); i++)
        if ('0' <= S[i] && S[i] <= '9')
            ret = ret * 10 + S[i] - '0';
    x = ret * f;
    return (is);
}
ostream &operator <<(ostream &os, __int128_t x) {
    ostream::sentry s(os);
    if (s) {
        __uint128_t tmp = x < 0 ? -x : x;
        char buffer[128];
        char *d = end(buffer);

        do {
            --d;
            *d = "0123456789"[tmp % 10];
            tmp /= 10;
        } while (tmp != 0);

        if (x < 0) {
            --d;
            *d = '-';
        }
        int len = end(buffer) - d;

        if (os.rdbuf()->sputn(d, len) != len) {
            os.setstate(ios_base::badbit);
        }
    }
    return os;
}

__int128_t stoll(string &S) {
    __int128_t ret = 0;
    int f = 1;
    if (S[0] == '-') f = -1; 
    for (int i = 0; i < S.length(); i++)
        if ('0' <= S[i] && S[i] <= '9')
            ret = ret * 10 + S[i] - '0';
    return ret * f;
}
__int128_t gcd(__int128_t a, __int128_t b) {
    return b ? gcd(b, a % b) : a;
}
__int128_t lcm(__int128_t a, __int128_t b) {
    return a / gcd(a, b) * b;
    // lcmが__int128_tに収まる必要あり
}

string to_string(ld x, int k) { // xの小数第k位までをstring化する
    assert(k >= 0);
    stringstream ss;
    ss << setprecision(k + 2) << x;
    string s = ss.str();
    if (s.find('.') == string::npos) s += '.';
    int pos = s.find('.');
    for (int i = 0; k >= (int)s.size() - 1 - pos; i++) s += '0';
    s.pop_back();
    if (s.back() == '.') s.pop_back();
    return s;

    // stringstream ss; // 第k+1位を四捨五入して第k位まで返す
    // ss << setprecision(k + 1) << x;
    // string s = ss.str();
    // if (s.find('.') == string::npos) s += '.';
    // int pos = s.find('.');
    // for (int i = 0; k > (int)s.size() - 1 - pos; i++) s += '0';
    // if (s.back() == '.') s.pop_back();
    // return s;
}

string to_string(__int128_t x) {
    string ret = "";
    if (x < 0) {
        ret += "-";
        x *= -1;
    }
    while (x) {
        ret += (char)('0' + x % 10);
        x /= 10;
    }
    reverse(ret.begin(), ret.end());
    return ret;
}
string to_string(char c) {
    string s = "";
    s += c;
    return s;
}

struct SXor128 {
    uint64_t x = 88172645463325252LL;
    unsigned Int() {
        x = x ^ (x << 7);
        return x = x ^ (x >> 9);
    }
    unsigned Int(unsigned mod) {
        x = x ^ (x << 7);
        x = x ^ (x >> 9);
        return x % mod;
    }
    unsigned Int(unsigned l, unsigned r) {
        x = x ^ (x << 7);
        x = x ^ (x >> 9);
        return x % (r - l + 1) + l;
    }
    double Double() {
        return double(Int()) / UINT_MAX;
    }
} rnd;

struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};

template<class T> size_t HashCombine(const size_t seed,const T &v){
    return seed^(hash<T>()(v)+0x9e3779b9+(seed<<6)+(seed>>2));
}
template<class T,class S> struct hash<pair<T,S>>{
    size_t operator()(const pair<T,S> &keyval) const noexcept {
        return HashCombine(hash<T>()(keyval.first), keyval.second);
    }
};
template<class T> struct hash<vector<T>>{
    size_t operator()(const vector<T> &keyval) const noexcept {
        size_t s=0;
        for (auto&& v: keyval) s=HashCombine(s,v);
        return s;
    }
};
template<int N> struct HashTupleCore{
    template<class Tuple> size_t operator()(const Tuple &keyval) const noexcept{
        size_t s=HashTupleCore<N-1>()(keyval);
        return HashCombine(s,get<N-1>(keyval));
    }
};
template <> struct HashTupleCore<0>{
    template<class Tuple> size_t operator()(const Tuple &keyval) const noexcept{ return 0; }
};
template<class... Args> struct hash<tuple<Args...>>{
    size_t operator()(const tuple<Args...> &keyval) const noexcept {
        return HashTupleCore<tuple_size<tuple<Args...>>::value>()(keyval);
    }
};

vector<mint> _fac, _finv, _inv;
void COMinit(int N) {
    _fac.resize(N + 1);
    _finv.resize(N + 1);
    _inv.resize(N + 1);
    _fac[0] = _fac[1] = 1;
    _finv[0] = _finv[1] = 1;
    _inv[1] = 1;
    for (int i = 2; i <= N; i++) {
        _fac[i] = _fac[i-1] * mint(i);
        _inv[i] = -_inv[MOD % i] * mint(MOD / i);
        _finv[i] = _finv[i - 1] * _inv[i];
    }
}

mint FAC(int N) {
    if (N < 0) return 0;
    return _fac[N];
}
mint COM(int N, int K) {
    if (N < K) return 0;
    if (N < 0 or K < 0) return 0;
    return _fac[N] * _finv[K] * _finv[N - K];
}
mint PERM(int N, int K) {
    if (N < K) return 0;
    if (N < 0 or K < 0) return 0;
    return _fac[N] *  _finv[N - K];
}
mint NHK(int N, int K) {
    if (N == 0 && K == 0)  return 1;
    return COM(N + K - 1, K);
}

#pragma endregion

class Compress {
public:
    int sz = 0;
    unordered_map<int, ushort> Z;    // 元の値 -> 圧縮した値
    unordered_map<ushort, int> UZ;   // 圧縮した値 -> 元の値

    Compress(const vector<int> &V, int base = 0) {
        this->sz = base;
        set<int> s(V.begin(), V.end());

        for (int x : s) {
            this->Z[x] = this->sz;
            this->UZ[this->sz] = x;
            this->sz++;
        }
    }
    
    Compress(const vector<int> &V1, const vector<int> &V2, int base = 0) {
        this->sz = base;
        vector<int> V3 = V2;
        V3.insert(V3.end(), V1.begin(), V1.end());
        set<int> s(V3.begin(), V3.end());

        for (int x : s) {
            this->Z[x] = this->sz;
            this->UZ[this->sz] = x;
            this->sz++;
        }
    }

    Compress(const vector<int> &V1, const vector<int> &V2, const vector<int> &V3, int base = 0) {
        this->sz = base;
        vector<int> V4 = V1;
        V4.insert(V4.end(), V2.begin(), V2.end());
        V4.insert(V4.end(), V3.begin(), V3.end());
        set<int> s(V4.begin(), V4.end());

        for (int x : s) {
            this->Z[x] = this->sz;
            this->UZ[this->sz] = x;
            this->sz++;
        }
    }

    vector<ushort> zip(const vector<int> &V) {
        vector<ushort> ret((int)V.size());
        for (int i = 0; i < (int)V.size(); i++) {
            ret[i] = Z[V[i]];
        }
        return ret;
    }

    // vector<int> unzip(const vector<ushort> &V) {
    //     vector<int> ret = V;
    //     for (int i = 0; i < (int)V.size(); i++) {
    //         ret[i] = UZ[ret[i]];
    //     }
    //     return ret;
    // }

    int size() { return sz; }

    int encode(int x) { return Z[x]; }
    int decode(int x) { return UZ[x]; }
};

ushort bit[5001][5001];
struct BIT2D {
    int H, W;
    BIT2D(int _H, int _W) : H(_H + 1), W(_W + 1) {
    }

    // (x, y)にwを足す
    void add(int x, int y, ushort w) {
        // if (x < 0 or x >= H or y < 0 or y >= W) return ; // 範囲外の時は足さない
        assert(x >= 0 && x < H && y >= 0 && y < W);
        for (int a = (++y, ++x); a <= H; a += a & -a) {
            for (int b = y; b <= W; b += b & -b) {
                bit[a][b] += w;
            }
        }
    }

    // [(0, 0) , (x, y)]の和　閉区間
    ushort sum(int x, int y) {
        if (x < 0 or y < 0) return 0; // x, y < 0の時は0
        // if (x >= H) x = H - 1; // x >= H, y >= W のときは x = H - 1, y = W - 1
        // if (y >= W) y = W - 1;
        assert(x < H && y < W);

        ushort ret = 0;
        for (int a = (++y, ++x); a > 0; a -= a & -a) {
            for (int b = y; b > 0; b -= b & -b) {
                ret += bit[a][b];
            }
        }
        return ret;
    }

    // [(x1, y1) , (x2, y2)] の和
    ushort sum(int x1, int y1, int x2, int y2) {
        // if (x1 > x2 or y1 > y2) return 0; // x1 > x2, y1 > y2の時は何もしない
        // if (x1 > x2) swap(x1, x2); // x1 > x2, y1 > y2の時はswap
        // if (y1 > y2) swap(y1, y2);
        assert(x1 <= x2 && y1 <= y2);
        return sum(x2, y2) - sum(x2, y1 - 1) - sum(x1 - 1, y2) +
            sum(x1 - 1, y1 - 1);
    }

    ushort get(int x, int y) {
        assert(x >= 0 && x < H && y >= 0 && y < W);
        int x1 = x, x2 = x, y1 = y, y2 = y;
        if (x1 > x2 or y1 > y2) return 0;
        return sum(x2, y2) - sum(x2, y1 - 1) - sum(x1 - 1, y2) +
            sum(x1 - 1, y1 - 1);
    }

    void set(int x, int y, ushort w) {
        ushort s = get(x, y);
        add(x, y, -s + w);
    }
};

signed main() {
	int N, Q;
    cin >> N >> Q;
    vector<int> X(N), Y(N);
    for (int i = 0; i < N; i++) cin >> X[i] >> Y[i];

	Compress CX(X, 0); // ここにAとCを入れてはいけない(Q²はデカすぎるので)
	Compress CY(Y, 0);
    vector<ushort> X1 = CX.zip(X);
    vector<ushort> Y1 = CY.zip(Y);

    BIT2D bit(CX.size() + 1, CY.size() + 1);
    for (int i = 0; i < N; i++) {
        bit.add(X1[i], Y1[i], 1);
    }

    vector<int> A(Q), B(Q), C(Q), D(Q);
    for (int i = 0; i < Q; i++) cin >> A[i] >> B[i] >> C[i] >> D[i];
    // 左下(A[i], B[i]), 右上(C[i], D[i]) の矩形領域

    Compress CX2(X, A, C, 0);
    vector<ushort> X2 = CX2.zip(X);
    X.clear();
    sort(X2.begin(), X2.end());
    vector<ushort> A2 = CX2.zip(A);
    A.clear();
    vector<ushort> C2 = CX2.zip(C);
    C.clear();

    Compress CY2(Y, B, D, 0);
    vector<ushort> Y2 = CY2.zip(Y);
    Y.clear();
    sort(Y2.begin(), Y2.end());
    vector<ushort> B2 = CY2.zip(B);
    B.clear();
    vector<ushort> D2 = CY2.zip(D);
    D.clear();

    for (int i = 0; i < Q; i++) {
        // cout << A[i] << " " << B[i] << " " << C[i] << " " << D[i] << endl;
        auto itl = lower_bound(X2.begin(), X2.end(), A2[i]);
        if (itl == X2.end()) {
            cout << 0 << endl;
            continue;
        }
        auto itr = upper_bound(X2.begin(), X2.end(), C2[i]);
        if (itr == X2.begin()) {
            cout << 0 << endl;
            continue;
        }
        itr--;

        int l = CX.encode(CX2.decode(*itl));
        int r = CX.encode(CX2.decode(*itr));

        auto itd = lower_bound(Y2.begin(), Y2.end(), B2[i]);
        if (itd == Y2.end()) {
            cout << 0 << endl;
            continue;
        }
        auto itu = upper_bound(Y2.begin(), Y2.end(), D2[i]);
        if (itu == Y2.begin()) {
            cout << 0 << endl;
            continue;
        }
        itu--;

        int d = CY.encode(CY2.decode(*itd));
        int u = CY.encode(CY2.decode(*itu));

        // cout << l << " " << r << " " << d << " " << u << endl;

        cout << bit.sum(l, d, r, u) << endl;
    }
}
accuracy: 0.25
time_ms: 810
memory_kb: 165392
final_rank: 20

code_snippet: // (⁠◕⁠ᴗ⁠◕⁠✿⁠)

// #pragma GCC target("avx2")
// #pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#define rep(i, n) for (ll i = 0; i < (n); i++)
#define srep(i, s, n) for (ll i = s; i < (n); i++)
#define len(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
using namespace std;
template<typename T> using vc = vector<T>;
template<typename T> using vv = vc<vc<T>>;
template<typename T> using vvv = vv<vc<T>>;
using vi = vc<int>;using vvi = vv<int>; using vvvi = vv<vi>;
using ll = long long;using vl = vc<ll>;using vvl = vv<ll>; using vvvl = vv<vl>;
using ld = long double; using vld = vc<ld>; using vvld = vc<vld>; using vvvld = vc<vvld>;
using uint = unsigned int;
using ull = unsigned long long;
const ld pi = 3.141592653589793;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
// const ll mod = 1000000007;
const ll mod = 998244353;
inline bool inside(ll y, ll x, ll H, ll W) {return 0 <= (y) and (y) < (H) and 0 <= (x) and (x) < (W); }

#define debug(var)  do{std::cout << #var << " : \n";view(var);}while(0)
template<typename T> void view(T e){cout << e << endl;}
template<typename T> void view(const vc<T>& v){for(const auto& e : v){ cout << e << " "; } cout << endl;}
template<typename T> void view(const vv<T>& vv){ for(const auto& v : vv){ view(v); } }

int main(){
    int N, M; cin >> N >> M;
    set<ll> totx = {INF}, toty = {INF};
    vc<pair<ll, ll>> points(N);
    rep(i, N){
        ll x, y; cin >> x >> y;
        points[i] = {x, y};
        totx.insert(x);
        toty.insert(y);
    }
    map<ll, ll> px, py;
    int H = 1;
    for (auto x : totx){
        px[x] = H;
        H++;
    }
    int W = 1;
    for (auto y : toty){
        py[y] = W;
        W++;
    }
    vv<int> cmsm(H + 1, vc<int>(W + 1, 0));
    for (auto [x, y] : points){
        cmsm[px[x]][py[y]]++;
    }
    rep(i, H + 1) rep(j, W + 1){
        if (i > 0) cmsm[i][j] += cmsm[i - 1][j];
        if (j > 0) cmsm[i][j] += cmsm[i][j - 1];
        if (i > 0 && j > 0) cmsm[i][j] -= cmsm[i - 1][j - 1];
    }

    rep(i, M){
        ll xl, yl, xr, yr; cin >> xl >> yl >> xr >> yr;
        auto xlit = totx.lower_bound(xl);
        auto xrit = totx.upper_bound(xr);
        auto ylit = toty.lower_bound(yl);
        auto yrit = toty.upper_bound(yr);
        if (*xlit != *xrit && *ylit != *yrit){
            int xlid = px[*xlit], xrid = px[*xrit], ylid = py[*ylit], yrid = py[*yrit];
            xlid--; ylid--; xrid--; yrid--;
            cout<< cmsm[xrid][yrid] - cmsm[xrid][ylid] - cmsm[xlid][yrid] + cmsm[xlid][ylid] << endl;
        }else cout << 0 << endl;
    }
}
accuracy: 1
time_ms: 1360
memory_kb: 102352
final_rank: 14

code_snippet: #include<bits/stdc++.h>
using namespace std;

template<class T>
struct merge_sort_tree{
    int n;
    vector<vector<T>> x;
    merge_sort_tree()=default;
    merge_sort_tree(const vector<T> &vec):n((int)vec.size()){
        x.resize(n*2);
        for(int i=0;i<n;i++)x[n+i]={vec[i]};
        for(int i=n-1;i;i--){
            merge(x[i*2].begin(),x[i*2].end(),x[i*2+1].begin(),x[i*2+1].end(),back_inserter(x[i]));
        }
    }
    
    int cntLess(int l,int r,T query)const{
        l+=n,r+=n;
        int ret=0;
        while(l<r){
            if(l&1){
                ret+=lower_bound(x[l].begin(),x[l].end(),query)-x[l].begin(),l++;
            }
            if(r&1){
                r--,ret+=lower_bound(x[r].begin(),x[r].end(),query)-x[r].begin();
            }
            l>>=1,r>>=1;
        }
        return ret;
    }
    
    int cntLesseq(int l,int r,T query)const{
        l+=n,r+=n;
        int ret=0;
        while(l<r){
            if(l&1){
                ret+=upper_bound(x[l].begin(),x[l].end(),query)-x[l].begin(),l++;
            }
            if(r&1){
                r--,ret+=upper_bound(x[r].begin(),x[r].end(),query)-x[r].begin();
            }
            l>>=1,r>>=1;
        }
        return ret;
    }

    int cntMore(int l,int r,T query)const{
        int tot=max(0,min(r,n)-max(l,0));
        return tot-cntLesseq(l,r,query);
    }

    int cntMoreeq(int l,int r,T query)const{
        int tot=max(0,min(r,n)-max(l,0));
        return tot-cntLess(l,r,query);
    }

    template<class OStream> friend OStream &operator<<(OStream &os,const merge_sort_tree &clt){
        os<<'[';
        for(int i=0;i<clt.n;i++)os<<clt.x[clt.n+i][0]<<',';
        return os<<']';
    }
};

int main() {
    cin.tie(nullptr), ios::sync_with_stdio(false);
    int N, M;
    cin >> N >> M;
    vector<pair<int, int>> P(N);
    for (auto &p : P) cin >> p.first >> p.second;
    sort(P.begin(), P.end());
    vector<int> xs, ys;
    for (auto p : P) xs.push_back(p.first), ys.push_back(p.second);
    merge_sort_tree<int> tree(ys);
    while (M--) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        int l = lower_bound(xs.begin(), xs.end(), x1) - xs.begin();
        int r = upper_bound(xs.begin(), xs.end(), x2) - xs.begin();
        cout << tree.cntLesseq(l, r, y2) - tree.cntLess(l, r, y1) << '\n';
    }
}
accuracy: 1
time_ms: 510
memory_kb: 4084
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (long long i = 0; i < (long long)(n); i++)
#define rrep(i,start,end) for (long long i = start;i >= (long long)(end);i--)
#define repn(i,end) for(long long i = 0; i <= (long long)(end); i++)
#define reps(i,start,end) for(long long i = start; i < (long long)(end); i++)
#define repsn(i,start,end) for(long long i = start; i <= (long long)(end); i++)
#define each(p,a) for(auto &p:a)
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef vector<long long> vll;
typedef vector<pair<long long ,long long>> vpll;
typedef vector<vector<long long>> vvll;
typedef set<ll> sll;
typedef map<long long , long long> mpll;
typedef pair<long long ,long long> pll;
typedef tuple<long long , long long , long long> tpl3;
#define LL(...) ll __VA_ARGS__; input(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__; input(__VA_ARGS__)
#define Str(...) string __VA_ARGS__; input(__VA_ARGS__)
#define Ch(...) char __VA_ARGS__; input(__VA_ARGS__)
#define all(a)  (a).begin(),(a).end()
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
// << std::fixed << std::setprecision(10)
const ll INF = 1LL << 60;
const ld EPS = 1e-9;
 
inline ll lfloor(ll x,ll m){return (x - ((x % m+ m)%m))/m;}
inline ll positive_mod(ll a,ll m){return (a % m + m)%m;}
inline ll popcnt(ull a){ return __builtin_popcountll(a);}
template<class T> bool chmin(T& a, T b){if(a > b){a = b;return true;}return false;}
template<class T> bool chmax(T& a, T b){if(a < b){a = b;return true;}return false;}
template<typename T>
std::istream &operator>>(std::istream&is,std::vector<T>&v){for(T &in:v){is>>in;}return is;}
template<typename T>
std::ostream &operator<<(std::ostream&os,const std::vector<T>&v){for(auto it=std::begin(v);it!=std::end(v);){os<<*it<<((++it)!=std::end(v)?" ":"");}return os;}
template<class... T>void input(T&... a){(cin >> ... >> a);}
void print(){cout << endl;}
template<class T, class... Ts>void print(const T& a, const Ts&... b){cout << a;((cout << ' ' << b), ...);cout << endl;}
template<class T> void pspace(const T& a){ cout << a << ' ';}
void perr(){cerr << endl;}
template<class T, class... Ts>void perr(const T& a, const Ts&... b){cerr << a;((cerr << ' ' << b), ...);cerr << endl;}
void yes(bool i = true){ return print(i?"yes":"no"); }
void Yes(bool i = true){ return print(i?"Yes":"No"); }
void YES(bool i = true){ return print(i?"YES":"NO"); }
//grid探索用
vector<ll> _ta = {0,0,1,-1,1,1,-1,-1};
vector<ll> _yo = {1,-1,0,0,1,-1,1,-1};
bool isin(ll now_i,ll now_j,ll h,ll w){return (0<=now_i && now_i < h && 0 <= now_j && now_j < w);}
  
ll lpow(ll x,ll n){ll ans = 1;while(n >0){if(n & 1)ans *= x;x *= x;n >>= 1;}return ans;}
ll Modlpow(ll x,ll n,ll m){ll ans = 1;ll a = x%m;while(n >0){if(n & 1){ans *= a;ans%= m;}a *= a;a %= m;n >>= 1;}return ans;} 
const ll MOD9 = 998244353LL;
const ll MOD10 = 1000000007LL;

// ref https://hitonanode.github.io/cplib-cpp/segmenttree/merge_sort_tree.hpp
//1indexed
//静的配列aの[l,r)のうち値がx以下とかの個数をオンラインで求める
template <class T>
class MergeSortTree{
  public:
  ll n;
  vector<vector<T>> tree;
  
  MergeSortTree(const vector<T> &a){
    n = a.size();
    tree.resize(n * 2);
    rep(i,n){
      tree[n+i] = {a[i]};
    }
    for(ll i = n-1;i >= 1;i--){
      merge(tree[i * 2].begin(),tree[i * 2].end(),tree[i * 2 + 1].begin(),tree[i * 2 + 1].end(),back_inserter(tree[i]));
    }
  }

  //[l,r)でx未満
  ll cntLess(ll l,ll r,T x){
    l += n;
    r += n;
    ll ret = 0;
    while(l < r){
      if(l & 1){//演算してから足す
        ret += lower_bound(all(tree[l]),x) - tree[l].begin();
        l++;
      }
      if(r & 1){//演算する前に引く
        r--;
        ret += lower_bound(all(tree[r]),x) - tree[r].begin();
      }
      l>>=1;r>>=1;
    }
    return ret;
  }

  //x以下
  ll cntLesseq(ll l,ll r,T x){
    l += n;
    r += n;
    ll ret = 0;
    while(l < r){
      if(l & 1){//演算してから足す
        ret += upper_bound(all(tree[l]),x) - tree[l].begin();l++;
      }
      if(r & 1){//演算する前に引く
        r--;ret += upper_bound(all(tree[r]),x) - tree[r].begin();
      }
      l>>=1;r>>=1;
    }
    return ret;
  }

  //xより大きい
  ll cntMore(ll l,ll r,T x){
    ll total = max(0LL,min(r,n) - max(0LL,l));
    return total - cntLesseq(l,r,x);
  }

  //x以上
  ll cntMoreeq(ll l,ll r,T x){
    ll total = max(0LL,min(r,n) - max(0LL,l));
    return total - cntLess(l,r,x);
  }
};
 
int main(){
  ios::sync_with_stdio(false);cin.tie(nullptr);
  LL(n,m);
  vpll xy(n);
  rep(i,n){
    LL(x,y);
    xy[i] = {x,y};

  }

  sort(all(xy));
  vector<ll> a(n);
  rep(i,n){
    a[i] = xy[i].second;
  }
  MergeSortTree seg(a);
  while(m--){
    LL(x1,y1,x2,y2);
    ll l = lower_bound(all(xy),make_pair(x1,-INF)) - xy.begin();
    ll r = lower_bound(all(xy),make_pair(x2,INF)) - xy.begin();
    cout << seg.cntMoreeq(l,r,y1) - seg.cntMore(l,r,y2) << endl;
  }

}
accuracy: 1
time_ms: 870
memory_kb: 4456
final_rank: 5