Pagini recente » Cod sursa (job #1165068) | Cod sursa (job #3261684) | Cod sursa (job #2945119) | Cod sursa (job #1973516) | Cod sursa (job #2969208)
//este problema lca de pe infoarena
//prezentam aici o metoda care foloseste linearizarea a treia a arborelui
//care consta in parcurgerea arborelui si notarea in lista linearizata a
//fiecarui nod de fiecare data cand trecem prin el
//pentru dou noduri u, v, lca-ul lor este nodul cu cea mai mica adancime intre
//prima aparitie a lui u si prima aparitie a lui v in forma linearizata
#include <bits/stdc++.h>
using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");
int n, t;
vector<int> adi[100001];
int dpth[100001];
int apa[100001]; // prima aparitie a fiecarui nod
int linea[200001], lng;
vector<int> spta[200001]; // sparse table
void citire() {
fin >> n >> t;
int a;
for(int i = 2; i <= n; i++) {
fin >> a;
adi[a].push_back(i);
}
}
void calc_dpth(int nod, int d) {
dpth[nod] = d;
for(auto nou : adi[nod]) {
calc_dpth(nou, d + 1);
}
}
void linea3(int nod) {
linea[++lng] = nod;
apa[nod] = lng;
for(auto nou : adi[nod]) {
linea3(nou);
linea[++lng] = nod;
}
}
int compa(int nod1, int nod2) {
if(dpth[nod1] < dpth[nod2])
return nod1;
return nod2;
}
int main() {
citire();
calc_dpth(1, 0);
//facem linearizarea a treia a arborelui
linea3(1);
// for(int i = 1; i <= lng; i++) {
// cout << linea[i] << " ";
// }
// cout << endl;
//incepem sa precalculam sparse table (spta)
for(int i = 1; i <= lng; i++) {
spta[i].push_back(linea[i]);
}
//parcurgem toate puterile lui 2 pana la cea mai mare cat incape
for(int putere = 0; putere <= 17; putere++) {
for(int i = 1; i <= lng; i++) {
if(spta[i].size() == putere + 1 && (i + (1 << putere) <= lng) && spta[i + (1 << putere)].size() == putere + 1) {
spta[i].push_back(compa(spta[i][putere], spta[i + (1 << putere)][putere]));
}
}
}
// for(int i = 1; i <= lng; i++) {
// cout << i << ": ";
// for(auto it : spta[i]) {
// cout << it << " ";
// }
// cout << "\n";
// }
//procesam query-urile
int u, v, dife;
for(int i = 1; i <= t; i++) {
fin >> u >> v;
if(apa[u] > apa[v])
swap(u, v);
dife = apa[v] - apa[u];
//cazul in care coincid
if(dife == 0) {
fout << u << "\n";
continue;
}
//calculam cea mai mare putere a lui 2 mai mica sau egala cu dife
int pt = 17;
while((1 << pt) > dife) {
pt--;
}
//raspundem la query
fout << compa(spta[apa[u]][pt], spta[apa[v] - dife][pt]) << "\n";
}
return 0;
}