Pagini recente » Cod sursa (job #1940925) | Cod sursa (job #1186258) | Cod sursa (job #676302) | Cod sursa (job #431007) | Cod sursa (job #2368044)
#include <fstream>
#include <vector>
using namespace std;
ifstream fi("lca.in");
ofstream fo("lca.out");
const int nmax=1e5;
int n, m, ne;
int tata[nmax+5], euler[2*nmax+5], level[nmax+5], first[nmax+5], log2[2*nmax+5];
int dp[2*nmax+5][21];
vector <int> G[nmax+5];
void dfs(int nod, int lvl)
{
/// construieste sirurile euler, level si first
euler[++ne]=nod;
level[ne]=lvl;
first[nod]=ne;
for(auto vec:G[nod])
{
dfs(vec, lvl+1);
euler[++ne]=nod;
level[ne]=lvl;
}
}
void rmq(void)
{
/// construieste dp
log2[1]=0;
for(int i=2; i<=ne; i++)
log2[i]=log2[i/2]+1;
for(int i=1; i<=ne; i++)
dp[i][0]=i;
for(int j=1; j<=log2[ne]; j++)
for(int i=1; i+(1<<j)-1<=ne; i++)
{
dp[i][j]=dp[i][j-1];
if(level[dp[i+(1<<(j-1))][j-1]]<level[dp[i][j]])
dp[i][j]=dp[i+(1<<(j-1))][j-1];
}
}
int min_query(int x, int y)
{
/// returneaza indicele elementului minim din intervalul level[x...y]
if(x>y)
swap(x, y);
int range=y-x+1, lg=log2[range];
if(level[dp[x+(1<<lg)][lg]] < level[dp[y-(1<<lg)+1][lg]])
return dp[x+(1<<lg)][lg];
return dp[y-(1<<lg)+1][lg];
}
int lca(int nod1, int nod2)
{
/// returneaza cel mai apropiat stramos comun al nodurilor nod1 si nod2
return euler[min_query(first[nod1], first[nod2])];
}
int main()
{
fi>>n>>m;
for(int i=2; i<=n; i++)
{
fi>>tata[i];
G[tata[i]].push_back(i);
}
dfs(1, 0);
rmq();
while(m--)
{
int u, v;
fi>>u>>v;
fo<<lca(u, v)<<"\n";
}
fi.close();
fo.close();
return 0;
}