Pagini recente » Cod sursa (job #3269115) | Cod sursa (job #2207022) | Cod sursa (job #867662) | Cod sursa (job #1199161) | Cod sursa (job #3305113)
#include <bits/stdc++.h>
std::ifstream fin("lca.in");
std::ofstream fout("lca.out");
//#define fin std::cin
//#define fout std::cout
/*
LCA - Euler tour + RMQ
--------------
Gasim forma Euler a arborelui si momentul in care intra fiecare nod in parcurgere
si adancimea fiecaruia.
Precalculam pe adancimile din parcurgere minimul cu RMQ.
OBS: LCA-ul unor doua noduri X si Y o sa se afle intre momentele de intrare.
LCA-ul o sa aiba depth-ul minim gasit in parcurgerea euler intre cele doua momente
OBS: Pentru paduri cream o radcina fictiva -1.
*/
const int nmax = 1e5 + 5;
const int logmax = 20;
int n, q;
std::vector<int> graph[nmax];
int father[nmax];
int enter[nmax]; // enter[i] = cand apare prima data nodul i in parcurgerea euler
std::vector<int> euler; // parcurgerea euler
std::vector<int> depth; // depth-ul nodului euler[i] din parcurgerea euler
int rmq[logmax][2 * nmax]; // facem rmq pentru nod cu depth minim
int logarithm[2 * nmax];
void dfs(int node, int parent, int level)
{
enter[node] = euler.size();
euler.push_back(node);
depth.push_back(level);
for(auto adj : graph[node])
if(adj != parent)
{
dfs(adj, node, level + 1);
euler.push_back(node); // ne intoarcem in node
depth.push_back(level);
}
}
void buildRMQ()
{
logarithm[0] = logarithm[1] = 0;
for(int i = 2; i <= depth.size(); ++i)
logarithm[i] = logarithm[i / 2] + 1;
// doresc sa pastrez indici ca sa pot obtine nodul din parcurgere
for(int i = 0; i < depth.size(); ++i)
rmq[0][i] = i;
for(int i = 1; i <= logarithm[depth.size()]; ++i)
for(int j = 0; j <= depth.size() - (1 << i); ++j)
{
int first = rmq[i - 1][j];
int second = rmq[i - 1][j + (1 << (i - 1))];
rmq[i][j] = (depth[first] < depth[second] ? first : second);
}
}
int lca(int x, int y)
{
int left = enter[x];
int right = enter[y];
if(left > right)
std::swap(left, right);
int len = logarithm[right - left + 1];
int ans1 = rmq[len][left]; // gasesc indicele cu depth minim
int ans2 = rmq[len][right - (1 << len) + 1];
return (depth[ans1] < depth[ans2] ? euler[ans1] : euler[ans2]);
}
int main()
{
fin >> n >> q;
for(int i = 2; i <= n; ++i)
{
fin >> father[i];
graph[i].push_back(father[i]);
graph[father[i]].push_back(i);
}
int root = 1;
father[root] = 0;
dfs(root, 0, 0);
buildRMQ();
while(q--)
{
int x, y;
fin >> x >> y;
fout << lca(x, y) << "\n";
}
return 0;
}