Pagini recente » Cod sursa (job #2768186) | Cod sursa (job #2466783) | Istoria paginii runda/rar37/clasament | oji_go_10_3 | Cod sursa (job #2923681)
/// lca cu aint, ca sa aflam minimul pe interval :)
#include <bits/stdc++.h>
using namespace std;
int const N = 100'001;
vector <int> g[N];
vector <int> height, euler, first, segtree;
vector <bool> verif;
int n;
void init()
{
height.resize(n);
first.resize(n);
euler.reserve(n * 2);
verif.assign(n, false);
}
void dfs_euler(int node, int h)
{
verif[node] = 1;
height[node] = h;
first[node] = euler.size();
euler.push_back(node);
for(auto next: g[node])
{
if(!verif[next])
dfs_euler(next, h + 1), euler.push_back(node);
}
}
void build_segtree(int node, int start, int fin)
{
if(start == fin)
{
segtree[node] = euler[start];
}
else
{
int mij = (start + fin) / 2;
build_segtree(node * 2, start, mij);
build_segtree(node * 2 + 1, mij + 1, fin);
int fiu_st = segtree[node * 2], fiu_dr = segtree[node * 2 + 1];
if(height[fiu_st] < height[fiu_dr])
segtree[node] = fiu_st;
else
segtree[node] = fiu_dr;
}
}
int query_segtree(int node, int start, int fin, int st, int dr)
{
if(start > dr or fin < st)
return -1;
if(start >= st and fin <= dr)
return segtree[node];
int mij = (start + fin) / 2;
int fiu_st = query_segtree(node * 2, start, mij, st, dr);
int fiu_dr = query_segtree(node * 2 + 1, mij + 1, fin, st, dr);
if(fiu_st == -1)
return fiu_dr;
if(fiu_dr == -1)
return fiu_st;
if(height[fiu_st] < height[fiu_dr])
return fiu_st;
return fiu_dr;
}
int query(int x, int y)
{
int st = first[x];
int dr = first[y];
if(st > dr)
swap(st, dr);
return query_segtree(1, 0, euler.size() - 1, st, dr);
}
int main()
{
ifstream cin("lca.in");
ofstream cout("lca.out");
int q;
cin >> n >> q;
init();
for(int i = 0; i < n - 1 ; i++)
{
int parinte;
cin >> parinte;
g[parinte].push_back(i + 2);
}
dfs_euler(1, 0);
int m = euler.size();
segtree.resize(m * 4);
build_segtree(1, 0, m - 1);
for(int i = 0; i < q; i++)
{
int x, y;
cin >> x >> y;
cout << query(x, y) << '\n';
}
return 0;
}