Pagini recente » Cod sursa (job #1069362) | Cod sursa (job #1312065) | Cod sursa (job #2577028) | Cod sursa (job #827668) | Cod sursa (job #1200470)
#include<fstream>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXN = 200005;
ifstream fin("lca.in");
ofstream fout("lca.out");
vector<int> G[MAXN];
int E[MAXN], pos[MAXN], lvl[MAXN], lg[MAXN];
int RMQ[20][MAXN];
int n, m, lge;
void dfs(int u, int current_lvl)
{
E[++lge] = u;
lvl[lge] = current_lvl;
pos[u] = min(pos[u], lge);
for (int v : G[u])
{
dfs(v, current_lvl+1);
E[++lge] = u;
lvl[lge] = current_lvl;
}
}
void rmq()
{
//Base case RMQ
for (int j=1; j<=lge; ++j)
RMQ[0][j] = j;
//Precompute RMQ
for (int i=1; (1<<i) <= lge; ++i)
{
for (int j=1; j<=lge-(1<<i)+1; ++j)
{
if (lvl[RMQ[i-1][j]] <= lvl[RMQ[i-1][j+(1<<(i-1))]])
RMQ[i][j] = RMQ[i-1][j];
else
RMQ[i][j] = RMQ[i-1][j+(1<<(i-1))];
}
}
}
int main()
{
fin>>n>>m;
for (int parent=0, node = 2; node <= n; ++node)
{
fin>>parent;
G[parent].push_back(node);
}
//Set first appearance to infinity
for (int i=0; i<=n; ++i)
pos[i] = MAXN;
//Eulerian representation
dfs(1, 0);
//Preprocess RMQ
rmq();
//Precalculate the log
lg[1]=0;
for (int i=2; i<=lge; ++i)
lg[i]=lg[i/2]+1;
//Handle the queries
int u, v;
for (int k=1; k<=m; ++k)
{
fin>>u>>v;
int start = min(pos[u], pos[v]), finish = max(pos[u], pos[v]);
int diff = finish - start;
// E PE LEVELE BOULE!!!
//int ancestor = E[min(RMQ[lg[diff]][start], RMQ[lg[diff]][finish-(1<<lg[diff])+1])];
//We separate an interval into 2 largest possible intervals
//that have 2^z elements. One starts at the beginning at one finishes at the end
int ancestor;
if (lvl[RMQ[lg[diff]][start]] <= lvl[RMQ[lg[diff]][finish-(1<<lg[diff])+1]])
ancestor = E[RMQ[lg[diff]][start]];
else
ancestor = E[RMQ[lg[diff]][finish-(1<<lg[diff])+1]];
fout<<ancestor<<'\n';
}
return 0;
}