Pagini recente » Cod sursa (job #3199347) | Cod sursa (job #3203285) | Cod sursa (job #181250) | Cod sursa (job #2240305) | Cod sursa (job #3185841)
#include <fstream>
#include <vector>
using namespace std;
ifstream f("lca.in");
ofstream g("lca.out");
/// Reprezentarea Euler a unui arbore: de fiecare data cand intram intr-un nod, adaugam perechea
/// {nivel, nod} la reprezentarea euler
/// (si cand intram din tata in fiu, si cand revenim din fiu in tata)
/// LCA-ul dintre doua noduri este nodul cu nivel minim din intervalul dat de primele
/// aparitii ale celor doua noduri in reprezentarea Euler
/// 1. Facem reprezentarea Euler cu un DFS
/// 2. Facem un RMQ pe vectorul cu reprezentarea Euler (se retine perechea minima - se retine practic dupa nivelul minim)
/// 3. Determinam raspunsurile cu un query normal pe RMQ si luam nodul
int n, m, x, y, l, a, b;
int k[100005], kcurent;
pair < int, int > rmq[200005][25]; /// rmq[n][log n]
vector < int > v[100005];
pair < int, int > euler[200005]; /// 2*n => perechi de tipul {nivel, nod}
int ctr;
int prap[100005]; /// prima aparitie a fiecarui nod in reprezentarea euler
void dfs(int nivel, int nod) {
euler[++ctr] = { nivel, nod };
prap[nod] = ctr;
for (auto newnod : v[nod]) {
dfs(nivel + 1, newnod);
euler[++ctr] = { nivel, nod };
}
}
void create_rmq() {
/// un rmq pe reprezentarea euler
for (int j = 0; (1 << j) <= ctr; j++) {
for (int i = 1; i + (1 << j) - 1 <= ctr; i++) {
if (j == 0) {
rmq[i][j] = euler[i];
}
else {
rmq[i][j] = min(rmq[i][j - 1], rmq[i + (1 << (j - 1))][j - 1]);
}
}
}
}
void solve() {
for (int i = 2; i <= ctr; i++) {
k[i] = k[i - 1];
if ((1 << (k[i] + 1)) < i) {
k[i]++;
}
}
for (int t = 1; t <= m; t++) {
f >> a >> b;
x = prap[a]; y = prap[b];
l = y - x + 1; /// lungimea intervalului
g << min(rmq[x][k[l]], rmq[y-(1<<k[l])+1][k[l]]).second << '\n';
/// .first = nivelul , .second = nodul
}
}
int main()
{
f >> n >> m;
for (int i = 2; i <= n; i++) {
f >> x;
v[x].push_back(i);
}
dfs(0, 1); /// radacina = 1 , pe nivelul 0
create_rmq();
solve();
}