Pagini recente » Cod sursa (job #627319) | Cod sursa (job #1838190) | Cod sursa (job #1754838) | Cod sursa (job #1608680) | Cod sursa (job #1377544)
// Lvl[i]=nivelul fiecarei pozitii din parcurgerea Euler a arborelui
// First[i]=prima aparitie a nodului i in reprezentarea Euler a arborelui
#include <fstream>
#include <algorithm>
#include <vector>
using namespace std;
ifstream f("lca.in");
ofstream g("lca.out");
int N, M, x, RMQ[18][200002], First[100002], lg[200002], Euler[200002], Lvl[100002], y;
vector < int > G[100002];
void dfs(int nod, int level)
{
Lvl[nod]=level; Euler[++Euler[0]]=nod; First[nod]=Euler[0];
vector<int>::iterator it=G[nod].begin();
for (; it!=G[nod].end(); ++it)
dfs(*it, level+1), Euler[++Euler[0]]=nod;
}
int LCA(int nod1, int nod2)
{
int st=First[nod1], dr=First[nod2];
if (st>dr) swap(st, dr);
int Log=lg[dr-st+1], x=RMQ[Log][st], y=RMQ[Log][dr-(1<<Log)+1];
if (Lvl[x]<Lvl[y]) return x;
else return y;
}
int main()
{
f>>N>>M;
for (int i=2; i<=N; ++i)
f>>x, G[x].push_back(i);
dfs(1, 1); RMQ[0][1]=Euler[1];
for (int i=2; i<=Euler[0]; ++i)
lg[i]=lg[i/2]+1, RMQ[0][i]=Euler[i];
for (int i=1; (1<<i)<=Euler[0]; ++i)
for (int j=1; j<=Euler[0]-(1<<i)+1; ++j)
{
x=RMQ[i-1][j]; y=RMQ[i-1][j+(1<<(i-1))];
if (Lvl[x]<Lvl[y]) RMQ[i][j]=x;
else RMQ[i][j]=y;
}
for (int i=1; i<=M; ++i)
f>>x>>y, g<<LCA(x, y)<<'\n';
return 0;
}