Pagini recente » Cod sursa (job #624885) | Cod sursa (job #2634892) | Cod sursa (job #106788) | Cod sursa (job #158571) | Cod sursa (job #2969180)
//este problema lowest common ancestor de pe infoarena
//arborele este dat prin vector de tati, iar 1 este mereu radacina
//vom prezenta aici metoda de a determina lca-ul folosind o lista, pentru fiecare
//nod stocand ce nod se afla mai sus de e cu 1, 2, 4, 8, ... pozitii
//mai intai, aducem nodurile u si v pentru care vrem sa determinam lca-ul
//la acelasi nivel in arbore, urmand sa aflam lca pt u' si v'.
//cautam binar in sus si cand gasim cele mai de sus noduri care nu coincid pt u si v
//aducem u si v fix in acele pozitii
//rezolvarea aceasta NU AR OBTINE PUNCTAJ MAXIM PE INFOARENA, deoarece n este prea mare...
#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];
vector<int> ancestors[100001]; // tine minte stramosii pe pozitii puteri ale lui 2
void citire() {
fin >> n >> t;
int a;
for(int i = 2; i <= n; i++) {
fin >> a;
adi[a].push_back(i);
ancestors[i].push_back(a); // stramosul cu 1 mai sus (tatal) (2^(0) --> pozitia 0 in vector)
//cout << "--" << ancestors[i][0];
}
}
void calc_dpth(int nod, int d) {
dpth[nod] = d;
for(auto nou : adi[nod]) {
calc_dpth(nou, d + 1);
}
}
int main() {
citire();
//calculam adancimea la care se afla fiecare nod
calc_dpth(1, 0);
//cout << "a";
//acum stramosii cu 2^0 mai sus de fiecare nod sunt calculati. Vom calcula acum
//stramosii cu toate puterile mai sus, pana la 2^14
for(int putere = 1; putere < 17; putere++) {
//cout << "putere " << putere << "\n";
for(int nod = 1; nod <= n; nod++) {
//cout << "nod " << nod << ", ";
//verificam daca ne permite nodul de sus sa avansam (daca nodul cu putere mai sus are putere
//stramosi, ca poate are doar mai putini)
if(ancestors[nod].size() >= putere && ancestors[ancestors[nod][putere - 1]].size() >= putere) {
ancestors[nod].push_back(ancestors[ancestors[nod][putere - 1]][putere - 1]);
}
}
}
// for(int i = 1; i <= n; i++) {
// cout << "\n" << i << ": ";
// for(auto it : ancestors[i]) {
// cout << it << " ";
// }
// }
//citim query-urile
int u, v, dife;
for(int i = 1; i <= t; i++) {
fin >> u >> v;
//cout << i << ": " << u << ", " << v << "\n";
//aducem u si v pe aceeasi pozitie
if(dpth[u] < dpth[v]) {
dife = dpth[v] - dpth[u];
// int putere = 0;
// while(dife > 0) {
// if(dife % 2 == 1) {
// v = ancestors[v][putere];
// }
// dife /= 2;
// putere++;
// }
for(int pt = 16; pt >= 0; pt--) {
if((dife & (1 << pt)) != 0) {
v = ancestors[v][pt];
}
}
}
else if(dpth[v] < dpth[u]) {
//cout << "am intrat cu dife ";
dife = dpth[u] - dpth[v];
//cout << dife << "\n";
//int putere = 0;
for(int pt = 16; pt >= 0; pt--) {
if((dife & (1 << pt)) != 0) {
u = ancestors[u][pt];
}
}
// while(dife > 0) {
// if(dife % 2 == 1) {
// u = ancestors[u][putere];
// putere++;
// }
// dife /= 2;
// putere++;
// //cout << u << "\n";
// }
}
//acum nodurile au fost aduse pe aceeasi pozitie
//incepem cautarea de la cea mai mare putere a lui 2 mai mica su egala
//cu lungimea vectorului de ancestori
//cout << "---" << u << ", " << v << "\n";
if(u == v) {
fout << u << "\n";
continue;
}
for(int putere = ancestors[u].size() - 1; putere >= 0; putere--) {
//cout << putere << "-> ";
//cout << ancestors[u][putere] << ", " << ancestors[v][putere] << "\n";
if(ancestors[u].size() > putere && ancestors[u][putere] != ancestors[v][putere]) {
u = ancestors[u][putere];
v = ancestors[v][putere];
}
}
fout << ancestors[u][0] << "\n";
}
return 0;
}