Pagini recente » Cod sursa (job #815074) | Cod sursa (job #2901709) | Cod sursa (job #3346360) | Cod sursa (job #2856446) | Cod sursa (job #3346451)
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");
int n, m, k, euler[200005], niv[100001], first[100001], rmq[25][200005],
log2[100001], pow2[25];
vector<int> adj[100001];
void DFS(int root){
vector<int> it(n + 1, 0);
vector<int> st;
st.push_back(root);
while (!st.empty()){
int x = st.back();
if (it[x] == 0){
euler[++k] = x;
first[x] = k;
}
if (it[x] < adj[x].size()){
int y = adj[x][it[x]++];
niv[y] = niv[x] + 1;
st.push_back(y);
}
else{
st.pop_back();
if (!st.empty()){
euler[++k] = st.back();
}
}
}
}
void construct_rmq(){
pow2[0] = 1;
for (int i = 1; i <= k; i ++){
if (i > 1)
log2[i] = log2[i >> 1] + 1;
if (i <= 20)
pow2[i] = pow2[i - 1] << 1;
}
///minimul dintre doua pozitii din parcurgerea euler a arborelui
for (int i = 1; i <= k; i ++)
rmq[0][i] = i;
for (int j = 1; pow2[j] <= k; j ++)
for (int i = 1; i + pow2[j] - 1 <= k; i ++){
int u = rmq[j - 1][i], v = rmq[j - 1][i + pow2[j - 1]];
if (niv[euler[u]] < niv[euler[v]])
rmq[j][i] = u;
else
rmq[j][i] = v;
}
}
int query(int l, int r){
if (l > r)
swap (l, r);
int d = r - l + 1;
int j = log2[d];
int pl = rmq[j][l], pr = rmq[j][r - pow2[j] + 1];
if (niv[euler[pl]] < niv[euler[pr]])
return pl;
else
return pr;
}
int lca(int x, int y){
int pos = query(first[x], first[y]);
return euler[pos];
}
int main()
{
fin >> n >> m;
for (int i = 2, x; i <= n; i ++){
fin >> x;
adj[x].push_back(i);
}
DFS(1);
construct_rmq();
while (m --){
int x, y;
fin >> x >> y;
fout << lca(x, y) << '\n';
}
}