Link to this code: https://cses.fi/paste/08fc0fb0453775d1c6a112/
/**
 *    author: Saurav
 *    created: 2025.05.01 05:23:43
 *    We stop at Candidate Master in 2025
 **/

/* includes and all */

#include<bits/stdc++.h>
#ifndef ONLINE_JUDGE
#define debug(x) cout<<"errr----  "<< #x <<" " <<x<<endl 
#define print(v) do { \
                    cout << "vect--" << #v << " = [ "; \
                    for (int i = 0; i < v.size(); i++) { \
                        cout << v[i] << " "; \
                    } \
                    cout << " ]" << endl; \
                } while(0)
#define print2d(v) do { \
                    cout << "vect-- starts" << endl; \
                    for (int i = 0; i < v.size(); i++) { \
                        cout << "[" << " "; \
                        for (int j = 0; j < v[i].size(); j++) { \
                            cout << v[i][j] << " "; \
                        } \
                        cout << "]" << endl; \
                    } \
                    cout << "vect-- ends" << endl; \
                } while(0)
#define printmap(m) do { \
                    cout << "map-- starts" << endl; \
                    for (auto it = m.begin(); it != m.end(); ++it) { \
                        cout << it->first << " -> " << it->second << endl; \
                    } \
                    cout << "map-- ends" << endl; \
                } while(0)

#define printset(s) do { \
    cout << "set-- starts" << endl; \
    for (auto it = s.begin(); it != s.end(); ++it) { \
        cout << *it << endl; \
    } \
    cout << "set-- ends" << endl; \
} while(0)

#define printpp(v) do { \
                    cout << "vect--" << " = [ "; \
                    for (int i = 0; i < v.size(); i++) { \
                        cout << "(" << v[i].first << ", " << v[i].second << ") "; \
                    } \
                    cout << " ]" << endl; \
                } while(0)
#else
#define debug(x)
#define print(v)
#define print2d(v)
#define printmap(m)
#define printpp(v)
#endif
#define endl "\n"
#define MOD 1000000007
#define mod_add(a, b) (((a) % MOD + (b) % MOD) % MOD)
#define mod_sub(a, b) ((((a) % MOD - (b) % MOD) + MOD) % MOD)
#define mod_mul(a, b) (((1LL * (a) % MOD) * (b) % MOD) % MOD)
// #define int long long int
#define mn(a,b,c) min(a,min(b,c))
#define mx(a,b,c) max(a,max(b,c))
#define pp pair<int,int>
using namespace std;

/* write core logic here */
class SegmentTree {
private:
    int n;
    vector<vector<int>> tree;
    vector<vector<int>> left;
    vector<vector<int>> right;
    vector<int> data;

    // Function to build the segment tree
    void build(int node, int start, int end) {
        if (start == end) {
            // Leaf node will have a single element
            tree[node].push_back(data[start]);
            return;
        }

        int mid = start + (end - start) / 2;
        int left_child = 2 * node + 1;
        int right_child = 2 * node + 2;

        // Recursively build the left and right children
        build(left_child, start, mid);
        build(right_child, mid + 1, end);

        // Merge the sorted vectors from left and right children
        mergeVectors(tree[left_child], tree[right_child], tree[node]);
        cascade(tree[left_child], tree[node], left[node]);
        cascade(tree[right_child], tree[node], right[node]);
    }

    // Helper function to merge two sorted vectors
    void mergeVectors(const vector<int> &left, const vector<int> &right, vector<int> &merged) {
        merged.clear();
        merged.reserve(left.size() + right.size());
        merged.resize(left.size() + right.size());

        int i = 0, j = 0, k = 0;

        while (i < left.size() && j < right.size()) {
            if (left[i] <= right[j]) {
                merged[k++] = left[i++];
            }
            else {
                merged[k++] = right[j++];
            }
        }

        // Copy remaining elements
        while (i < left.size()) {
            merged[k++] = left[i++];
        }
        while (j < right.size()) {
            merged[k++] = right[j++];
        }
    }

    void cascade(vector<int> &prev , vector<int> &now, vector<int> &make){
        int i = 0;
        int j = 0;
        int size = now.size();
        make.clear();
        make.reserve(size);
        make.resize(size);
        while(j < size){
            if(i == prev.size()){
                make[j] = prev.size();
                j++;
                continue;
            }
            while(i<prev.size() && prev[i] < now[j]){
                i++;
            }
            make[j] = i;
            j++;
        }
    }

    // Function to perform the query
    int queryUtil(int node, int start, int end, int L, int R, int X, int idx) const {
        if (R < start || end < L) {
            // No overlap
            return 0;
        }

        if (L <= start && end <= R) {
            // Total overlap
            return idx;
        }

        // Partial overlap
        int mid = start + (end - start) / 2;
        int left_child = 2 * node + 1;
        int right_child = 2 * node + 2;

        int left_idx, right_idx;
        if(idx == tree[node].size()){
            left_idx = tree[left_child].size();
            right_idx = tree[right_child].size();
        }
        else{
            left_idx = left[node][idx];
            right_idx = right[node][idx];
        }

        int count_left = queryUtil(left_child, start, mid, L, R, X, left_idx);
        int count_right = queryUtil(right_child, mid + 1, end, L, R, X, right_idx);

        return count_left + count_right;
    }

public:
    // Constructor to initialize and build the segment tree
    SegmentTree(const vector<int> &input_data) {
        data = input_data;
        n = data.size();
        // Allocate enough space for the segment tree
        tree.resize(4 * n);
        left.resize(4 * n);
        right.resize(4 * n);
        build(0, 0, n - 1);
    }

    // Function to query the frequency of X in range [L, R]
    int query(int L, int R, int X) const {
        if (L < 0 || R >= n || L > R) {
            throw invalid_argument("Invalid query range.");
        }
        int idx = upper_bound(tree[0].begin(), tree[0].end(), X) - tree[0].begin();
        return queryUtil(0, 0, n - 1, L, R, X, idx);
    }


    void print_tree() {
        // cout << "Segment Tree:" << endl;
        // for (int i = 0; i < tree.size(); i++) {
        //     cout << "Node " << i << ": ";
        //     for (int j = 0; j < tree[i].size(); j++) {
        //         cout << tree[i][j] << " ";
        //     }
        //     cout << endl;
        // }
        cout << "Left:" << endl;
        for (int i = 0; i < left.size(); i++) {
            cout << "Node " << i << ": ";
            for (int j = 0; j < left[i].size(); j++) {
                cout << left[i][j] << " ";
            }
            cout << endl;
        }
        // cout << "Right:" << endl;
        // for (int i = 0; i < right.size(); i++) {
        //     cout << "Node " << i << ": ";
        //     for (int j = 0; j < right[i].size(); j++) {
        //         cout << right[i][j] << " ";
        //     }
        //     cout << endl;
        // }
    }
};
void solve(){
    int n,q;
    cin>>n>>q;
    vector<int> a(n);
    for(int i = 0; i<n; i++){
        cin>>a[i];
    }

    SegmentTree st(a);

    // st.print_tree();


    for(int i = 0; i<q; i++){
        int l,r,x1,x2;
        cin>>l>>r>>x1>>x2;
        l--;
        r--;
        int ans1 = st.query(l,r,x2);
        int ans2 = st.query(l,r,x1-1);
        cout<<ans1 - ans2<<endl;
    }
}
/* logic ends */

signed main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    #ifndef ONLINE_JUDGE
        freopen("Error.txt" , "w" , stderr);
    #endif
    int t;
    //cin>>t;
    t = 1;
    while(t--){
        solve();
    }
return 0;
}