// compile: make data // run: ./data < data.in #include <bits/stdc++.h> using namespace std; #pragma GCC optimize("O3,unroll-loops") #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") #ifdef LOCAL #include <debug/codeforces.h> #define debug(x...) _debug_print(#x, x); #define Debug(x...) _debug_print_format(#x, x); #else #define debug(x...) #define Debug(x...) #endif template<typename...Args> void print_(Args...args){((cout<<args<<" "),...)<<endl;} #define VI vector<int> #define VII vector<vector<int>> #define VIII vector<vector<vector<int>>> #define rep(i,a,b) for(int i=(a);i<(int)(b);++i) #define sz(v) ((int)(v).size()) #define print(...) print_(__VA_ARGS__); #define FIND(a, x) ((find(a.begin(),a.end(),(x))!=a.end())?1:0) #define cmin(x,...) x=min({(x), __VA_ARGS__}) #define cmax(x,...) x=max({(x), __VA_ARGS__}) #define INTMAX (int)(9223372036854775807) #define INF (int)(1152921504606846976) #define NaN (int)(0x8b88e1d0595d51d1) #define double long double #define int long long #define MAXN 200010 struct Tree { int n; vector<vector<int>> e; struct node { vector<node*> ch; node* parent = nullptr; int size, depth; }; vector<node> vertex; node *root; Tree(int V) { n = V; e.resize(n); vertex.resize(n); } void add_edge(int u, int v) { e[u].push_back(v), e[v].push_back(u); } int ind(node *x) {return x - &vertex[0]; } void build(int rt = 0) { function<void(int, int)> dfs = [&](int u, int pre) { vertex[u].size = 1; vertex[u].depth = u==ind(root) ? 0 : vertex[u].parent->depth + 1; for (int v: e[u]) { if (v == pre) continue; vertex[u].ch.push_back(&vertex[v]); vertex[v].parent = &vertex[u]; dfs(v, u); vertex[u].size += vertex[v].size; } }; root = &vertex[rt]; dfs(rt, -1); } void graphviz_dump(int plus = 0, string filename = "graph.dot") { FILE *f = fopen(filename.c_str(), "w"); fprintf(f, "digraph Tree {\n"); rep(i, 0, n) { node *x = &vertex[i]; fprintf(f, " %lld;\n"); } rep(i, 0, n) { node *x = &vertex[i]; for (auto y: x->ch) { fprintf(f, " %ld -> %ld;\n", x - &vertex[0], y - &vertex[0]); } } fprintf(f, "}\n"); } vector<vector<int>> hp; vector<vector<int>> ancestor() { vector<vector<int>> p(n, vector<int>(log2(n) + 1)); rep(i, 0, n) p[i][0] = vertex[i].parent ? ind(vertex[i].parent) : -1; rep(j, 1, log2(n)+1) rep(i, 0, n) p[i][j] = ~p[i][j-1] ? p[p[i][j-1]][j-1] : -1; return p; } int lca(int u, int v) { if (!hp.size()) hp = ancestor(); if (vertex[u].depth < vertex[v].depth) swap(u, v); for (int k = log2(n); k >= 0; --k) if (vertex[u].depth - (1<<k) >= vertex[v].depth) u = hp[u][k]; if (u == v) return u; for (int k = log2(n); k >= 0; --k) { if (hp[u][k] != hp[v][k]) { u = hp[u][k], v = hp[v][k]; } } return hp[u][0]; } }; int32_t main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); int n, q; cin >> n >> q; Tree g(n); rep(i, 0, n-1) { int x; cin >> x; g.add_edge(i+1, x-1); } g.build(0); // g.graphviz_dump(); // return 0; while (q--) { int u, v; cin >> u >> v; --u, --v; cout << g.lca(u, v) + 1 << '\n'; } return 0; }
No Comments