#include <bits/stdc++.h>   using namespace std;   int val[300000];   vector<pair<int, int> > ed[300000];   int fa[300000][20], maxt[300000][20], dfn[300000], dep[300000];   void dfs_bas(int u, int f) {     dep[u] = dep[f] + 1, dfn[u] = ++dfn[0];     fa[u][0] = f;     for (int i = 1; i < 20; i++)       fa[u][i] = fa[fa[u][i - 1]][i - 1],       maxt[u][i] = max(maxt[u][i - 1], maxt[fa[u][i - 1]][i - 1]);     for (int i = 0; i < ed[u].size(); i++) {       int v = ed[u][i].first;       if (v == f) continue;       maxt[v][0] = ed[u][i].second;       dfs_bas(v, u);     }   }   int LCA(int x, int y) {     if (dep[x] < dep[y]) swap(x, y);     for (int i = 19; i >= 0; i--)       if (dep[fa[x][i]] >= dep[y]) x = fa[x][i];     if (x == y) return x;     for (int i = 19; i >= 0; i--)       if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];     return fa[x][0];   }   int query_anc(int x, int d) {     int ans = 0;     for (int i = 19; i >= 0; i--)       if (d & (1 << i)) {         ans = max(ans, maxt[x][i]);         x = fa[x][i];       }     return ans;   }   int query_path(int x, int y) {     int l = LCA(x, y);     return max(query_anc(x, dep[x] - dep[l]), query_anc(y, dep[y] - dep[l]));   }   struct Tree {     int n;     vector<int> ed[500000];     int val[500000], calc[500000], arg[500000];     int fa[500000][20], dep[500000], dfn[500000], sz[500000], ev[500000];     void dfs_bas(int u, int f) {       fa[u][0] = f, dfn[u] = ++dfn[0], sz[u] = 1, dep[u] = dep[f] + 1;       for (int i = 1; i < 20; i++) fa[u][i] = fa[fa[u][i - 1]][i - 1];       for (int i = 0; i < ed[u].size(); i++) {         int v = ed[u][i];         if (v == f) continue;         dfs_bas(v, u);         sz[u] += sz[v];       }     }     int LCA(int x, int y) {       if (dep[x] < dep[y]) swap(x, y);       for (int i = 19; i >= 0; i--)         if (dep[fa[x][i]] >= dep[y]) x = fa[x][i];       if (x == y) return x;       for (int i = 19; i >= 0; i--)         if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];       return fa[x][0];     }   } Y;   struct BCJ {     int fa[500000];     void init(int n) {       for (int i = 1; i <= n; i++) fa[i] = i;     }     int fnd(int x) { return x == fa[x] ? x : fa[x] = fnd(fa[x]); }     void conn(int x, int y) { fa[fnd(x)] = fnd(y); }   } B;   struct e {     int a, b, c, t;   } ined[300000];   bool ccmp(e A, e B) { return A.c < B.c; }   bool tcmp(e A, e B) { return A.t < B.t; }   bool ydfncmp(int x, int y) { return Y.dfn[x] < Y.dfn[y]; }   int main() {     int n = 0, q = 0;     scanf( %d%d , &n, &q);     for (int i = 1; i <= n; i++) scanf( %d , &val[i]);     for (int i = 1; i < n; i++)       scanf( %d%d%d%d , &ined[i].a, &ined[i].b, &ined[i].c, &ined[i].t),           ed[ined[i].a].push_back(make_pair(ined[i].b, ined[i].t)),           ed[ined[i].b].push_back(make_pair(ined[i].a, ined[i].t));     dfs_bas(1, 0);     int c = n;     B.init(2 * n - 1);     sort(ined + 1, ined + n, ccmp);     for (int i = 1; i <= n; i++) Y.val[i] = val[i], Y.arg[i] = i;     for (int i = n - 1; i >= 1; i--) {       if (B.fnd(ined[i].a) != B.fnd(ined[i].b)) {         int u = B.fnd(ined[i].a), v = B.fnd(ined[i].b);         c++;         Y.ed[c].push_back(u), Y.ed[c].push_back(v);         B.conn(u, c), B.conn(v, c);         Y.val[c] = max(Y.val[u], Y.val[v]);         Y.ev[c] = ined[i].c;         if (Y.val[c] != Y.val[u]) {           Y.calc[c] = Y.calc[v], Y.arg[c] = Y.arg[v];         } else if (Y.val[c] != Y.val[v]) {           Y.calc[c] = Y.calc[u], Y.arg[c] = Y.arg[u];         } else {           Y.calc[c] =               max(max(Y.calc[u], Y.calc[v]), query_path(Y.arg[u], Y.arg[v]));           Y.arg[c] = Y.arg[u];         }       }     }     Y.dfs_bas(2 * n - 1, 0);     while (q--) {       int x = 0, v = 0;       scanf( %d%d , &v, &x);       int u = x;       for (int i = 19; i >= 0; i--)         if (Y.fa[u][i] && Y.ev[Y.fa[u][i]] >= v) u = Y.fa[u][i];       printf( %d %d n , Y.val[u], max(Y.calc[u], query_path(x, Y.arg[u])));     }   }