Problem:
LCA: Lowest Common Ancestor

For a rooted tree, find the lowest common ancestor of two nodes u and v.

The given tree consists of n nodes and every node has a unique ID from 0 to n-1 where 0 is the root.

Input

n
k0 c1 c2 ... ck0
k1 c1 c2 ... ck1
:
kn-1 c1 c2 ... ckn-1
q
u1 v1
u2 v2
:
uq vq

The first line of the input includes an integer n, the number of nodes of the tree.

In the next n lines, the information of node i is given. ki is the number of children of node i, and c1, ... cki are node IDs of 1st, ... kth child of node i.

In the next line, the number of queryies q is given. In the next q lines, pairs of u and v are given as the queries.

Output

For each query, print the LCA of u and v in a line.

Constraints

1 ≤ n ≤ 100000

1 ≤ q ≤ 100000

Sample Input 1

8
3 1 2 3
2 4 5
0
0
0
2 6 7
0
0
4
4 6
4 7
4 3
5 2

Sample Output 1

1
1
0
0

Solution in C++14 (judge verdict: Accepted)

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

template <typename Monoid>
struct SegmentTree{
private:
    using F = function<Monoid(Monoid, Monoid)>;
    int N{};
    vector<Monoid> node;
    F f;
    Monoid e;  // identity element

public:
    SegmentTree() = default;
    SegmentTree(F f, Monoid e):f(f), e(e){}
    void init(int sz){
        N = 1;
        while(N < sz) N <<= 1;
        node.assign(2*N-1, e);
    }
    void build(vector<Monoid>& v){
        int sz = int(v.size());
        init(sz);
        for(int i=0; i<sz; i++){
            node[i+N-1] = v[i];
        }
        for(int i=N-2; i>=0; i--){
            node[i] = f(node[i*2+1], node[i*2+2]);
        }
    }
    void update(int k, Monoid x){
        k += N-1;
        node[k] = x;
        while(k > 0){
            k = (k-1)/2;
            node[k] = f(node[2*k+1], node[2*k+2]);
        }
    }
    // [a,b)
    Monoid query(int a, int b){return query(a, b, 0, 0, N);}
    Monoid query(int a, int b, int k, int l, int r){
        if(b <= l || r <= a) return e;
        if(a <= l && r <= b) return node[k];
        Monoid vl, vr;
        vl = query(a, b, 2*k+1, l, (l+r)/2);
        vr = query(a, b, 2*k+2, (l+r)/2, r);
        return f(vl, vr);
    }
};

using P = std::pair<int,int>;


class LCA {
private:
    using Type = int;
    const int INF = 1 << 30;
    struct edge {
        int from, to, rev;
        Type cost;
        edge(int from, int to, int rev, Type cost) : from(from), to(to), rev(rev), cost(cost){}
    };
    int V = 0;
    int root = 0;
    std::vector<std::vector<edge> > graph;
    std::vector<int> depth, vs, ds, us;

    SegmentTree<P> rmq = SegmentTree<P>([](P a, P b){return min(a,b);},P(INF,-1));
    SegmentTree<Type> rsq = SegmentTree<Type>([](Type a, Type b){return a+b;}, 0);

    void dfs(int v, int p, int d, int &idx){
        vs[idx] = v;
        depth[v] = d;
        ds[v] = idx++;
        for(auto& e : graph[v]){
            if(e.to == p) continue;
            dfs(e.to, v, d+1, idx);
            vs[idx] = v;
            idx++;
        }
        us[v] = idx;
    }

public:
    LCA() = default;
    LCA(int V, int root = 0) : V(V), graph(V), depth(V), vs(V*2-1), ds(V), us(V), root(root){}
    void init(int n, int r = 0){
        V = n;
        graph.resize(V);
        depth.resize(V);
        vs.resize(V*2-1);
        ds.resize(V);
        us.resize(V);
        root = r;
    }
    void add_edge(int from, int to, Type cost = 1){
        graph[from].emplace_back(edge(from,to,int(graph[to].size()),cost));
        graph[to].emplace_back(edge(to,from,int(graph[from].size())-1,cost));
    }
    void build(){
        int idx = 0;
        dfs(root, -1, 0, idx);
        std::vector<P> depv(idx);
        for(int i=0;i<idx;i++){
            depv[i] = P(depth[vs[i]], vs[i]);
        }
        rmq.build(depv);
        std::vector<Type> cstv(idx);
        for(int i=0;i<V;i++){
            for(auto& e : graph[i]){
                if(depth[e.from] < depth[e.to]){
                    cstv[ds[e.to]] = e.cost;
                    cstv[us[e.to]] = -e.cost;
                }
            }
        }
        rsq.build(cstv);
    }
    int query(int u, int v){
        return rmq.query(min(ds[u],ds[v]), max(ds[u],ds[v])+1).second;
    }
    Type dist(int u, int v){
        int w = query(u, v);
        return rsq.query(ds[root], ds[u]+1) + rsq.query(ds[root], ds[v]+1) - 2*rsq.query(ds[root], ds[w]+1);
    }
    void update(int v, Type cost){
        rsq.update(ds[v], cost);
        rsq.update(us[v], -cost);
    }
};

int main() {
    int n, q;
    cin >> n;
    LCA lca(n);
    for(int i=0;i<n;i++){
        int k;
        cin >> k;
        for(int j=0;j<k;j++){
            int c;
            cin >> c;
            lca.add_edge(i,c);
        }
    }
    lca.build();
    cin >> q;
    for(int i=0;i<q;i++){
        int u, v;
        cin >> u >> v;
        cout << lca.query(u, v) << endl;
    }
    return 0;
}