Language: C++

#include <iostream>
#include <vector>
#include <cassert>
#include <algorithm>
#include <cstdio>
#include <tuple>

using namespace std;
typedef long long ll;
typedef pair<int, int> P;

template<int V>
struct LowestCommonAncestor {
    const static int LG = 25;
    int ro[LG][V];
    int dps[V];
    vector<int> g[V];
    void add(int i, int j) {
        g[i].push_back(j);
        g[j].push_back(i);
    }
    void dfs(int p, int b) {
        assert(ro[0][p] == -1);
        ro[0][p] = b;
        dps[p] = (b == -1) ? 0 : dps[b]+1;
        for (int d: g[p]) {
            if (d == b) continue;
            dfs(d, p);
        }
    }
    void exec(int r) {
        memset(ro, -1, sizeof(ro));
        dfs(r, -1);
        for (int i = 0; i < LG-1; i++) {
            for (int j = 0; j < V; j++) {
                ro[i+1][j] = (ro[i][j] == -1) ? -1 : ro[i][ro[i][j]];
            }
        }
    }
    int query(int l, int r) {
        if (dps[l] < dps[r]) swap(l, r);
        int dd = dps[l]-dps[r];
        for (int i = LG-1; i >= 0; i--) {
            if (dd < (1<<i)) continue;
            dd -= 1<<i;
            l = ro[i][l];
        }
        if (l == r) return l;
        for (int i = LG-1; i >= 0; i--) {
            if (ro[i][l] == ro[i][r]) continue;
            l = ro[i][l]; r = ro[i][r];
        }
        return ro[0][l];
    }
};

struct Tree {
    using D = ll;
    struct Node;
    using NP = Node*;
    static Node last_d;
    static NP last;
    struct Node {
        NP l, r;
        int sz;
        D v;
        Node(D v) :l(last), r(last), sz(1), v(v) {}
        Node() :l(nullptr), r(nullptr), sz(0) {}
        static NP make(NP x) {
//            pool[pc] = *x;
//            pc++;
//            return &pool[pc-1];
            NP u = new Node();
            *u = *x;
            return u;
        }
        void push() {

        }
        NP update() {
            sz = 1+l->sz+r->sz;
            return this;
        }
        int lb(D a) {
            if (!sz) return 0;
            if (a <= v) return l->lb(a);
            return l->sz + 1 + r->lb(a);
        }
        int ub(D a) {
            if (!sz) return 0;
            if (v <= a) return l->sz + 1 + r->ub(a);
            return l->ub(a);
        }
        D get(int k) {
            if (k == l->sz) return v;
            if (k < l->sz) {
                return l->get(k);
            } else {
                return r->get(k- (l->sz+1));
            }
        }
    } *n;

    static uint xor128(){
        static uint x=123456789,y=362436069,z=521288629,w=88675123;
        uint t;
        t=(x^(x<<11));x=y;y=z;z=w;
        return( w=(w^(w>>19))^(t^(t>>8)) );
    }
    static NP merge(NP l, NP r) {
        if (!l->sz) return r;
        if (!r->sz) return l; 
        l->push(); r->push();
        if ((int)(xor128() % (l->sz + r->sz)) < l->sz) {
            l = Node::make(l);
            l->r = merge(l->r, r);
            return l->update();
        } else {
            r = Node::make(r);
            r->l = merge(l, r->l);
            return r->update();
        }
    }
    static pair<NP, NP> split(NP x, int k) {
        if (!x->sz) return {last, last};
        x->push();
        x = Node::make(x);
        if (k <= x->l->sz) {
            auto y = split(x->l, k);
            x->l = y.second;
            y.second = x->update();
            return y;
        } else {
            auto y = split(x->r, k- x->l->sz -1);
            x->r = y.first;
            y.first = x->update();
            return y;
        }
    }

    Tree() : n(last) {}
    Tree(NP n) : n(n) {}
    int sz() {
        return n->sz;
    }
    Tree insert(D v) {
        auto u = split(n, lb(v));
        return Tree(merge(merge(u.first, new Node(v)), u.second));
    }
    int count(D v) {
        return ub(v) - lb(v);
    }
    int lb(D v) {
        return n->lb(v);
    }
    int ub(D v) {
        return n->ub(v);
    }
    D get(int k) {
        return n->get(k);
    }
};
Tree::Node Tree::last_d = Tree::Node();
Tree::NP Tree::last = &last_d;

const int MN = 100100;

LowestCommonAncestor<MN> lca;
int n, q;
int d[MN];
vector<int> g[MN];
int root[MN];
Tree tr[MN];

void dfs(int p, int b) {
    root[p] = b;
    if (p) {
        tr[p] = tr[b].insert(d[p]);
    }
    for (int d: g[p]) {
        if (d == b) continue;
        dfs(d, p);
    }
}

int calc(int a, int u) {
    if (a == -1) return 0;
    int res = 0;
    if (d[a] < u) res++;
    return tr[a].lb(u);
}

int main() {
    int n, q;
    scanf("%d %d", &n, &q);
    for (int i = 0; i < n; i++) {
        scanf("%d", d+i);
    }
    for (int i = 0; i < n-1; i++) {
        int a, b;
        scanf("%d %d", &a, &b); a--; b--;
        lca.add(a, b);
        g[a].push_back(b);
        g[b].push_back(a);
    }
    lca.exec(0);
    tr[0] = Tree().insert(d[0]);
    dfs(0, -1);
    for (int i = 0; i < q; i++) {
        int a, b, w;
        scanf("%d %d %d", &a, &b, &w); a--; b--;
        int c = lca.query(a, b);
        int l = 0, r = 1e9+10;
        while (r-l > 1) {
            int md = (r+l)/2;
            int u = calc(a, md)+calc(b, md)-2*calc(c, md);
            if (d[c] < md) u++;
            if (u < w) {
                l = md;
            } else {
                r = md;
            }
        }
        printf("%d\n", l);
    }
    return 0;
}

Compiler output:
a.cc: In instantiation of 'void LowestCommonAncestor<V>::exec(int) [with int V = 100100]':
a.cc:206:13:   required from here
  206 |     lca.exec(0);
      |     ~~~~~~~~^~~
a.cc:32:15: error: 'memset' was not declared in this scope
   32 |         memset(ro, -1, sizeof(ro));
      |         ~~~~~~^~~~~~~~~~~~~~~~~~~~
a.cc:6:1: note: 'memset' is defined in header '<cstring>'; this is probably fixable by adding '#include <cstring>'
    5 | #include <cstdio>
  +++ |+#include <cstring>
    6 | #include <tuple>