Pagini recente » Cod sursa (job #1396012) | Cod sursa (job #1751395) | Cod sursa (job #1941778) | Cod sursa (job #730017) | Cod sursa (job #2858080)
#include <fstream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <cstring>
#include <climits>
#include <unordered_map>
#define NMAX 100003
//Solutia cu Euler
using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");
int n,m,kEuler;
int niv[NMAX];//nivelul fiecarui nod
int primaAp[2*NMAX];//prima aparitie in nodurile euler
int noduriEuler[2*NMAX];//vectorul de muchii euler
int rmq[128][2*NMAX];
int p[2*NMAX];//precalcularea puterilor de 2
vector<int>graf[NMAX];
void dfs(int nod,int nivel)
{
niv[nod]=nivel;
primaAp[nod]=++kEuler;
noduriEuler[kEuler]=nod;
for(int i=0; i<graf[nod].size(); i++)
{
dfs(graf[nod][i],nivel+1);
noduriEuler[++kEuler]=nod;
}
}
void lca(int L,int R)
{
int lung = R - L + 1;
int val = p[lung];
if(niv[rmq[val][L]]< niv[rmq[val][R+1 - (1 << val)]] )
{
fout<<rmq[val][L]<<"\n";
return;
}
fout<<rmq[val][R+1 - (1 << val)]<<"\n";
}
int main()
{
fin >> n >> m;
for(int i=2; i<=n; i++)
{
int x;
fin>>x;
graf[x].push_back(i);
}
dfs(1,0);
p[1]=0;
for(int i=2; i<=kEuler; i++)
{
p[i]=p[i/2]+1;
}
//aplic rmq pe vectorul de euler
for(int i=1; i<=kEuler; i++)
{
rmq[0][i]=noduriEuler[i];
}
for(int i=1; (1<<i)<=kEuler; i++)
{
int lungSecv=(1<<i);
for(int j=1; j+lungSecv-1<=kEuler; j++)
{
int st=j;
int dr=j+(1<<(i-1))-1;
if(niv[rmq[i-1][st]]<niv[rmq[i-1][dr]])
{
rmq[i][j]=rmq[i-1][st];
}
else{
rmq[i][j]=rmq[i-1][dr];
}
}
}
for(int i=1; i<=m; i++)
{
int x,y;
fin>>x>>y;
lca(min(primaAp[x],primaAp[y]),max(primaAp[x],primaAp[y]));
}
return 0;
}