Pagini recente » Cod sursa (job #269520) | Cod sursa (job #376529) | Cod sursa (job #2116406) | Cod sursa (job #2655409) | Cod sursa (job #3298875)
/**
Solutie: Arbori de intervale
Complexitate: O(n + m log n)
*/
#include <bits/stdc++.h>
using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");
const int INF = 2'000'000'000;
const int MAX_DIM = 100'000;
int euler[MAX_DIM << 1];/// euler[i] - al i-lea nod in parcurgerea Euler
int niv[MAX_DIM << 1]; /// height[i] - nivelul nodului euler[i]
int firstPos[MAX_DIM]; /// firstPos[i] - prima pozitie a nodului i in parcurgere
int aint[MAX_DIM << 4]; /// nodul pentru care se atinge min{height[st..dr]}
int k;
vector<int> G[MAX_DIM]; /// arborele cu radacina in 1
int n, m;
void dfs(int nod, int dist) { /// parcurgerea euleriana / Euler tour
euler[++k] = nod;
niv[k] = dist;
firstPos[nod] = k;
for (int vec : G[nod]) {
dfs(vec, dist + 1);
euler[++k] = nod;
niv[k] = dist;
}
}
void build(int nod, int st, int dr) {
if (st == dr) {
/// nodul st are adancimea minima
aint[nod] = st;
return;
}
int mid = (st + dr) >> 1;
build(nod << 1, st, mid);
build(nod << 1 | 1, mid + 1, dr);
if (niv[aint[nod << 1]] <= niv[aint[nod << 1 | 1]])
aint[nod] = aint[nod << 1];
else
aint[nod] = aint[nod << 1 | 1];
}
void query(int nod, int st, int dr, int a, int b, int &sol, int &niv_sol) {
if (a <= st && dr <= b) {
if (niv[aint[nod]] < niv_sol) {
sol = euler[aint[nod]];
niv_sol = niv[aint[nod]];
}
return;
}
int mid = (st + dr) >> 1;
if (a <= mid)
query(nod << 1, st, mid, a, b, sol, niv_sol);
if (b > mid)
query(nod << 1 | 1, mid + 1, dr, a, b, sol, niv_sol);
}
int lca(int u, int v) {
int st = firstPos[u], dr = firstPos[v];
if (st > dr) {
int aux = st;
st = dr;
dr = st;
}
int sol = INF, niv_sol = INF;
query(1, 1, k, st, dr, sol, niv_sol);
return sol;
}
int main() {
fin >> n >> m;
for (int i = 2; i <= n; i++) {
int x;
fin >> x;
G[x].push_back(i);
}
dfs(1, 0);
build(1, 1, k);
while (m--) {
int u, v;
fin >> u >> v;
fout << lca(u, v) << "\n";
}
fin.close();
fout.close();
return 0;
}