Pagini recente » Cod sursa (job #3347510) | Cod sursa (job #2763467) | Cod sursa (job #3271045) | Cod sursa (job #3344204) | Cod sursa (job #3346093)
#include <bits/stdc++.h>
using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");
vector<int> graf[100001];
int depth[100001], n, q, x, y;
int euler[200002], primaAp[100001], nivel[100001];
int timer, lg[200002], st[20][200002];
void dfs(int nod, int parinte) //EULER TOUR
{
timer++;
euler[timer]=nod;
nivel[timer]=depth[nod];
if (primaAp[nod]==0)
{
primaAp[nod]=timer;
}
for (auto vecin: graf[nod])
{
if (vecin==parinte) continue;
depth[vecin]=depth[nod]+1;
dfs(vecin, nod);
timer++;
euler[timer]=nod;
nivel[timer]=depth[nod];
}
}
void build_sparse()//in sparse retinem pozitia nivelului mic
{
for (int i=1; i<=timer; i++)
{
st[0][i]=i;
}
for (int k=1;(1<<k)<=timer; k++)
{
for (int i=1; i+(1<<k)-1<=timer; i++)
{
int stg=st[k-1][i];
int drp=st[k-1][i+(1<<(k-1))];
if(nivel[stg]<=nivel[drp])
{
st[k][i]=stg;
}
else
{
st[k][i]=drp;
}
}
}
return;
}
int lcaquery(int a, int b)
{
int stanga=primaAp[a];
int dreapta=primaAp[b];
if (stanga>dreapta)
{
swap(stanga, dreapta);
}
int k=lg[dreapta-stanga+1];
int p1=st[k][stanga];
int p2=st[k][dreapta-(1<<k)+1];
int poz;
if (nivel[p1]<nivel[p2])
{
poz=p1;
}
else
{
poz=p2;
}
return euler[poz];
}
int main()
{
fin>>n>>q;
for (int i=2; i<=n; i++)
{
fin>>x;
graf[x].push_back(i);
graf[i].push_back(x);
}
depth[1]=1;
dfs(1, 0);
lg[1]=0;
for (int i=2; i<=timer; i++) //calculez logaritmii pt poz
{
lg[i]=lg[i/2]+1;
}
build_sparse();
for (int i=1; i<=q; i++)
{
fin>>x>>y;
fout<<lcaquery(x, y)<<'\n';
}
return 0;
}