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

const int MAXN = 1e5 + 5;
const int BLOCK_SIZE = 450; // Xấp xỉ sqrt(M)

struct Operation {
    int x, y;
} ops[MAXN];

struct Event {
    int op_idx, type; // type: +1 (thêm), -1 (bớt)
};

struct Query {
    int id, l, r;
};

int n, m, q;
int initial_a[MAXN];
int results[MAXN];
int is_active[MAXN]; // Đánh dấu thao tác có đang phủ vị trí p hay không
vector<Event> events_at[MAXN];
vector<Query> queries_at[MAXN];

// Cấu trúc để quản lý việc "nhảy" qua một khối thao tác
struct BlockMapping {
    int target[MAXN];    // target[v]: giá trị v biến thành sau khi qua khối
    int timestamp[MAXN]; // Dùng để tránh memset (Lazy Reset)
    int current_time = 0;

    void rebuild(int b_idx) {
        current_time++;
        int start = (b_idx - 1) * BLOCK_SIZE + 1;
        int end = min(m, b_idx * BLOCK_SIZE);

        // Duyệt ngược từ cuối khối về đầu để xây dựng bảng ánh xạ
        for (int i = end; i >= start; i--) {
            if (is_active[i]) {
                int from = ops[i].x;
                int to = ops[i].y;

                timestamp[from] = current_time;
                // Nếu 'to' đã được ánh xạ bởi một lệnh phía sau trong khối
                if (timestamp[to] == current_time) {
                    target[from] = target[to];
                } else {
                    target[from] = to;
                }
            }
        }
    }

    int jump(int b_idx, int val) {
        return (timestamp[val] == current_time) ? target[val] : val;
    }
} mapping[MAXN / BLOCK_SIZE + 5];

// Trả lời câu hỏi bằng cách duyệt trâu đoạn lẻ và nhảy qua khối nguyên
int solve_query(int val, int l, int r) {
    int b_l = (l - 1) / BLOCK_SIZE + 1;
    int b_r = (r - 1) / BLOCK_SIZE + 1;

    if (b_l == b_r) {
        for (int i = l; i <= r; i++) 
            if (is_active[i] && val == ops[i].x) val = ops[i].y;
        return val;
    }

    // 1. Xử lý đoạn lẻ ở khối đầu
    int end_l = b_l * BLOCK_SIZE;
    for (int i = l; i <= end_l; i++)
        if (is_active[i] && val == ops[i].x) val = ops[i].y;

    // 2. Nhảy qua các khối nguyên ở giữa
    for (int b = b_l + 1; b < b_r; b++) {
        val = mapping[b].jump(b, val);
    }

    // 3. Xử lý đoạn lẻ ở khối cuối
    int start_r = (b_r - 1) * BLOCK_SIZE + 1;
    for (int i = start_r; i <= r; i++)
        if (is_active[i] && val == ops[i].x) val = ops[i].y;

    return val;
}

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

    if (!(cin >> n >> m)) return 0;
    for (int i = 1; i <= n; i++) cin >> initial_a[i];

    for (int i = 1; i <= m; i++) {
        int l, r, x, y;
        cin >> l >> r >> x >> y;
        ops[i] = {x, x + y};
        events_at[l].push_back({i, 1});
        events_at[r + 1].push_back({i, -1});
    }

    cin >> q;
    for (int i = 1; i <= q; i++) {
        int p, l, r;
        cin >> p >> l >> r;
        queries_at[p].push_back({i, l, r});
    }

    // Đường quét qua từng vị trí trên mảng A
    for (int p = 1; p <= n; p++) {
        if (events_at[p].empty() && queries_at[p].empty()) continue;

        set<int> changed_blocks;
        for (auto &e : events_at[p]) {
            is_active[e.op_idx] += e.type;
            changed_blocks.insert((e.op_idx - 1) / BLOCK_SIZE + 1);
        }

        // Chỉ xây dựng lại bảng ánh xạ cho những khối có sự thay đổi
        for (int b_idx : changed_blocks) {
            mapping[b_idx].rebuild(b_idx);
        }

        for (auto &q : queries_at[p]) {
            results[q.id] = solve_query(initial_a[p], q.l, q.r);
        }
    }

    for (int i = 1; i <= q; i++) cout << results[i] << "\n";

    return 0;
}