/// KoJa
#include <bits/stdc++.h>
using namespace std;
#define task "test"
#define pb push_back
#define SZ(a) (a).begin(), (a).end()
#define SZZ(a, Begin, End) (a) + (Begin), (a) + (Begin) + (End)
#define BIT(a) (1LL << (a))
#define vec vector
#define fi first
#define se second
#define mp make_pair
#define MASK(x, i) (((x) >> (i))&1)

typedef long long ll;
typedef pair<int, int> ii;

template <class T>
inline bool maximize(T &a, const T &b) { return (a < b ? (a = b, 1) : 0); }
template <class T>
inline bool minimize(T &a, const T &b) { return (a > b ? (a = b, 1) : 0); }
void fastio()
{
    ios_base::sync_with_stdio(NULL);
    cin.tie(NULL);
    if (fopen(task ".inp", "r"))
    {
        freopen(task ".inp", "r", stdin);
        freopen(task ".out", "w", stdout);
    }
    else if (fopen(task ".in", "r"))
    {
        freopen(task ".in", "r", stdin);
        freopen(task ".out", "w", stdout);
    }
}
const int N = int(1e6) + 5;
const ll INF = 1e18;
int n, m;
struct Rectangle
{
    int x, y, u, v;
    Rectangle(){}
    Rectangle(int _x, int _y, int _u, int _v)
    {
        x = _x;
        y = _y;
        u = _u;
        v = _v;
    }
} rect[N], queries[N];

struct Line
{
    int x, l, r, id, type;
    Line(){}
    Line(int _x, int _l, int _r, int _id, int _type)
    {
        x = _x;
        l = _l;
        r = _r;
        id = _id;
        type = _type;
    }
    bool operator < (const Line &other) { return ((x < other.x)||((x == other.x)&&(type < other.type)));}
};

vec<ii> points;
vec<int> val;
vec<Line> sweepline;
void init()
{
    cin >> n >> m;
    ++n;
    rect[1] = Rectangle(-1e9, -1e9, 1e9, 1e9);
    val.pb(-1e9);
    val.pb(1e9);
    for(int i = 2; i <= n; i++)
    {
        cin >> rect[i].x >> rect[i].y >> rect[i].u >> rect[i].v;
        val.pb(rect[i].y);
        val.pb(rect[i].v);
    }
    for(int i = 1; i <= m; i++)
    {
        cin >> queries[i].x >> queries[i].y >> queries[i].u >> queries[i].v;
        val.pb(queries[i].y);
        val.pb(queries[i].v);
    }
}
vec<vec<int>> adj(N);
int depth[N], par[N][20], parPoints[N];
void dfs(int u, int p)
{
    for(int v : adj[u])
    {
        if(v == p)
            continue;
        par[v][0] = u;
        depth[v] = depth[u] + 1;
        dfs(v, u);
    }
}
int lca(int u, int v)
{
    if(depth[u] < depth[v])
        swap(u, v);
    for(int i = 19; i >= 0; i--)
        if(depth[par[u][i]] >= depth[v])
            u = par[u][i];
    if(u == v)
        return u;
    for(int i = 19; i >= 0; i--)
        if(par[u][i] != par[v][i])
        {
            u = par[u][i];
            v = par[v][i];
        }
    return par[u][0];
}
int getDist(int u, int v)
{
    return depth[u] + depth[v] - 2 * depth[lca(u, v)];
}
ii qu[N];
class SegmentTree
{
private:
    int n;
    vec<int> st, lz;
    void pushDown(int id)
    {
        if(lz[id] == 0)
            return;
        st[2 * id] = lz[id];
        st[2 * id + 1] = lz[id];
        lz[2 * id] = lz[id];
        lz[2 *id + 1] = lz[id];
        lz[id] = 0;
    }
    void update(int u, int v, int val, int l, int r, int id)
    {
        if((u > v)||(l > r)||(l > v)||(u > r))
            return;
        if((u <= l)&&(r <= v))
        {
            st[id] = val;
            lz[id] = val;
            return;
        }
        pushDown(id);
        int mid = (l + r) >> 1;
        update(u, v, val, l, mid, 2*id);
        update(u, v, val, mid + 1, r, 2*id + 1);
        if(st[2 * id])
            st[id] = st[2 * id];
        if(st[2*id + 1])
            st[id] = st[2*id + 1];
    }
    int getVal(int pos, int l, int r, int id)
    {
        if((l > r)||(l > pos)||(pos > r))
            return 0;
        if(l == r)
            return st[id];
        pushDown(id);
        int mid = (l + r) >> 1;
        int res = 0;
        if(pos <= mid)
            res = max(res, getVal(pos, l, mid, 2*id));
        else
            res = max(res, getVal(pos, mid + 1, r, 2*id + 1));
        return res;
    }
public:
    SegmentTree(int _n = 0)
    {
        this->n = _n;
        st = lz = vec<int>(4 * n + 7, 0);
    }
    void update(int l, int r, int val) { return update(l, r, val, 1, n, 1);}
    int getVal(int pos) { return getVal(pos, 1, n, 1);}
} it;
void process(const int &tc)
{
    sort(SZ(val));
    val.erase(unique(SZ(val)), val.end());
    for(int i = 1; i <= m; i++)
    {
        queries[i].y = lower_bound(SZ(val), queries[i].y) - val.begin() + 1;
        queries[i].v = lower_bound(SZ(val), queries[i].v) - val.begin() + 1;
        points.pb(ii(queries[i].x, queries[i].y));
        points.pb(ii(queries[i].u, queries[i].v));
    }
    sort(SZ(points));
    points.erase(unique(SZ(points)), points.end());
    for(int i = 1; i <= n; i++)
    {
        rect[i].y = lower_bound(SZ(val), rect[i].y) - val.begin() + 1;
        rect[i].v = lower_bound(SZ(val), rect[i].v) - val.begin() + 1;
        sweepline.pb(Line(rect[i].x, rect[i].y, rect[i].v, i, 0));
        sweepline.pb(Line(rect[i].u, rect[i].y, rect[i].v, i, 2));
    }
    for(int i = 1; i <= m; i++)
    {
        int id1 = lower_bound(SZ(points), ii(queries[i].x, queries[i].y)) - points.begin() + 1;
        int id2 = lower_bound(SZ(points), ii(queries[i].u, queries[i].v)) - points.begin() + 1;
        qu[i] = ii(id1, id2);
    }

    for(int i = 1; i <= (int)points.size(); i++)
        sweepline.pb(Line(points[i - 1].fi, points[i - 1].se, points[i - 1].se, i, 1));




    sort(SZ(sweepline));
    it = SegmentTree((int)val.size());
    for(auto &x : sweepline) {
        if(x.type == 2)
        {
            it.update(x.l, x.r, par[x.id][0]);
        }
        else
        {
            int u = it.getVal(x.r);
            if(u != 0)
            {
                if(x.type == 0)
                {
                    par[x.id][0] = u;
                    adj[x.id].pb(u);
                    adj[u].pb(x.id);
                }
                else
                    parPoints[x.id] = u;
            }
            if(x.type == 0)
            {
                it.update(x.l, x.r, x.id);
            }
        }
    }
    depth[0] = -1;
    depth[1] = 0;
    dfs(1, -1);
    for(int i = 1; i < 20; i++)
        for(int u = 1; u <= n + 1; u++)
            par[u][i] = par[par[u][i - 1]][i - 1];
    for(int i = 1; i <= m; i++)
        cout << getDist(parPoints[qu[i].fi], parPoints[qu[i].se]) << '\n';
}
int main()
{
    fastio();
    int t = 1;
    // cin >> t;
    for (int i = 1; i <= t; i++)
    {
        init();
        process(i);
    }
    return 0;
}
/*
    l <= u && v <= r
*/

