#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;
}