Pagini recente » Cod sursa (job #2636966) | Cod sursa (job #2438432) | Cod sursa (job #2569030) | Cod sursa (job #1720383) | Cod sursa (job #2703518)
#include <bits/stdc++.h>
using namespace std;
const int MAXL = 20;
vector<vector<int>> link; // link[i][j] -> al 2^i-lea stramos al lui j
vector<int> depth; // adancimea fiecarui nod
vector<vector<int>> graph; // arborele
void DFS(int node, int par, int dep) {
// Construiesc stramosii.
depth[node] = dep;
link[node][0] = par;
for (int i = 0; i + 1 < MAXL; ++i) {
int anc = link[node][i];
if (anc != -1) link[node][i + 1] = link[anc][i];
}
// Apelez recursiv pe fii.
for (auto vec : graph[node]) {
if (vec == par) continue;
DFS(vec, node, dep + 1);
}
}
int LCA(int a, int b) {
// Truc de lenesi, ca sa ma asigur
// ca a e mai adanc decat b.
if (depth[a] < depth[b])
swap(a, b);
// a -> al d-lea stramos al lui a
// (ca sa asigur depth[a] == depth[b])
int d = depth[a] - depth[b];
for (int i = 0; d; ++i) {
if (d % 2) a = link[a][i];
d /= 2;
}
// Important sa verific ca nu cumva a == b == LCA
// (altfel nu e corect, pentru ca la final returnez parent[a])
if (a == b) return a;
// Ma duc in sus cat timp a != b
// Practic, optimizez codul:
// while (a != b) a = parent[a], b = parent[b];
for (int i = MAXL - 1; i >= 0; --i)
if (link[a][i] != link[b][i])
// avansez 2^i pasi in sus.
a = link[a][i], b = link[b][i];
// assert crapa programul daca conditia nu e adevarata.
// Nu modifica cu nimic programul, doar e util ca sa mai
// reduci din debugging cand ceva nu merge.
assert(link[a][0] == link[b][0]);
// link[0][a] == al 2^0-lea stramos al lui a == parent[a].
return link[a][0];
}
int main() {
ifstream cin("lca.in");
ofstream cout("lca.out");
int n, m; cin >> n >> m;
graph.assign(n, {});
depth.assign(n, -1);
link.assign(n, vector<int>(MAXL, -1));
for (int i = 1; i < n; ++i) {
int par; cin >> par; --par;
graph[par].push_back(i);
}
DFS(0, -1, 0);
for (int i = 0; i < m; ++i) {
int a, b; cin >> a >> b; --a; --b;
cout << 1 + LCA(a, b) << '\n';
}
return 0;
}