#include <bits/stdc++.h>
using namespace std;
const int LOG = 20; // 2^19 > 2e5 là đủ, dùng 20 cho an toàn
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, Q;
if (!(cin >> N >> Q)) return 0;
vector<int> H(N);
for (int i = 0; i < N; ++i) cin >> H[i];
// 1) Nearest Greater to Left / Right
vector<int> L(N, -1), R(N, -1);
{
vector<int> st;
for (int i = 0; i < N; ++i) {
while (!st.empty() && H[st.back()] < H[i]) st.pop_back();
if (!st.empty()) L[i] = st.back();
st.push_back(i);
}
}
{
vector<int> st;
for (int i = N - 1; i >= 0; --i) {
while (!st.empty() && H[st.back()] < H[i]) st.pop_back();
if (!st.empty()) R[i] = st.back();
st.push_back(i);
}
}
// 2) high / low neighbor
vector<int> hi(N, -1), lo(N, -1);
for (int i = 0; i < N; ++i) {
if (L[i] == -1 && R[i] == -1) {
hi[i] = lo[i] = -1;
} else if (L[i] == -1) {
hi[i] = R[i];
lo[i] = -1;
} else if (R[i] == -1) {
hi[i] = L[i];
lo[i] = -1;
} else {
if (H[L[i]] > H[R[i]]) {
hi[i] = L[i];
lo[i] = R[i];
} else {
hi[i] = R[i];
lo[i] = L[i];
}
}
}
// 3) Doubling tables
// 3a) hi-jumps and max R along the path
vector<array<int, LOG>> up(N), rightJ(N), leftJ(N);
vector<array<int, LOG>> mxUp(N), mxLeft(N);
for (int i = 0; i < N; ++i) {
up[i][0] = hi[i];
mxUp[i][0] = (R[i] == -1 ? -1 : R[i]); // khi "đứng" ở i trước khi nhảy
rightJ[i][0]= R[i];
leftJ[i][0] = L[i];
mxLeft[i][0]= (R[i] == -1 ? -1 : R[i]); // tương tự: đứng tại i
}
for (int k = 1; k < LOG; ++k) {
for (int i = 0; i < N; ++i) {
// hi
int mid = up[i][k-1];
if (mid == -1) { up[i][k] = -1; mxUp[i][k] = mxUp[i][k-1]; }
else {
up[i][k] = up[mid][k-1];
mxUp[i][k] = max(mxUp[i][k-1], mxUp[mid][k-1]);
}
// right chain
int rmid = rightJ[i][k-1];
rightJ[i][k] = (rmid == -1 ? -1 : rightJ[rmid][k-1]);
// left (L-chain) và max R trên các vị trí đã “đứng”
int lmid = leftJ[i][k-1];
if (lmid == -1) { leftJ[i][k] = -1; mxLeft[i][k] = mxLeft[i][k-1]; }
else {
leftJ[i][k] = leftJ[lmid][k-1];
mxLeft[i][k]= max(mxLeft[i][k-1], mxLeft[lmid][k-1]);
}
}
}
auto farRightIndex = [&](int x, int D)->int {
if (x < 0) return -1;
int cur = x;
for (int k = LOG-1; k >= 0; --k) {
int y = rightJ[cur][k];
if (y != -1 && y <= D) cur = y;
}return cur; // last index ≤ D reachable by only R-jumps
};
auto stepsToEnter = [&](int x, int C, int D)->pair<int,int> {
// trả về (index hạ cánh trong [C,D], số bước R) — nếu không thể, trả (-1,-1)
if (x == -1) return {-1,-1};
int cur = x, steps = 0;
// nhảy những khối vẫn còn < C
for (int k = LOG-1; k >= 0; --k) {
int y = rightJ[cur][k];
if (y != -1 && y < C && y <= D) {
cur = y;
steps += 1<<k;
}
}
int y = R[cur];
if (y == -1 || y > D) return make_pair(-1,-1);
++steps; cur = y; // bước để vào [C,D]
if (cur < C || cur > D) return make_pair(-1,-1);
return {cur, steps};
};
auto pickStart = [&](int A, int B, int D)->int {
// đi ngược theo L từ B, giữ max R trên các vị trí đã “đứng” ≤ D
int cur = B;
int mx = (R[cur] == -1 ? -1 : R[cur]);
if (mx > D) return -1;
for (int k = LOG-1; k >= 0; --k) {
int y = leftJ[cur][k];
if (y != -1 && y >= A) {
int candMax = max(mx, mxLeft[cur][k]);
if (candMax <= D) { // còn an toàn thì lùi tiếp
mx = candMax;
cur = y;
}
}
}
return cur;
};
auto climbHiWhileSafe = [&](int cur, int C, int D, long long &used)->int {
// leo theo hi xa nhất sao cho:
// 1) mọi nút "đứng" có R ≤ D
// 2) từ điểm hạ cánh, đẩy phải tới cùng vẫn < C
for (int k = LOG-1; k >= 0; --k) {
int nxt = up[cur][k];
if (nxt == -1) continue;
if (mxUp[cur][k] > D) continue; // vi phạm (1)
int last = farRightIndex(nxt, D);
if (last >= C) continue; // vi phạm (2): đã có thể tới C
cur = nxt;
used += 1LL<<k;
}
return cur;
};
while (Q--) {
int A,B,C,D;
cin >> A >> B >> C >> D;
int s = pickStart(A,B,D);
if (s == -1) { cout << -1 << '\n'; continue; }
if (s >= C && s <= D) { cout << 0 << '\n'; continue; }
long long ans = 0;
int cur = s;
bool ok = true;
while (true) {
// leo hi tối đa khi còn "an toàn" và vẫn chưa thể vào [C,D] chỉ bằng phải
long long used = 0;
cur = climbHiWhileSafe(cur, C, D, used);
ans += used;
// nếu từ cur đẩy phải tới cùng vẫn chưa tới C -> thử 1 bước low
int last = farRightIndex(cur, D);
if (last < C) {
if (lo[cur] == -1) { ok = false; break; }
// bước lo phải hợp lệ vì hiện tại R[cur] ≤ D (được đảm bảo khi leo)
cur = lo[cur];++ans;
if (cur >= C && cur <= D) break;
// lặp tiếp
continue;
}
// bây giờ chỉ cần nhảy phải tối thiểu để vào [C,D]
auto got = stepsToEnter(cur, C, D);
if (got.first == -1) { ok = false; break; }
ans += got.second;
cur = got.first;
break;
}
if (!ok) cout << -1 << '\n';
else cout << ans << '\n';
}
return 0;
}