Pagini recente » Istoria paginii algoritmiada-2010/runda-4/solutii/matrice3 | Cod sursa (job #3358942) | Atasamentele paginii Solutie Matrice3 | Cod sursa (job #3358916) | Cod sursa (job #3358894)
#include <bits/stdc++.h>
using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");
int n, m, tour;
vector<int> eulerTour, depth;
vector<int> L[100005];
unordered_map<int, int> first;
int e[200005], rmq[18][200005], pows[20];
void EulerTour(int k, int adancime) {
depth.push_back(adancime);
eulerTour.push_back(k);
first[k] = eulerTour.size() - 1;
for (auto &w : L[k]) {
EulerTour(w, adancime + 1);
depth.push_back(adancime);
eulerTour.push_back(k);
}
}
void BuildRMQ() {
for (int i = 2; i <= tour; i++) {
e[i] = 1 + e[i / 2];
}
pows[0] = 1;
for (int i = 1; i <= e[tour]; i++) {
pows[i] = 2 * pows[i - 1];
}
for (int i = 1; i <= tour; i++) {
rmq[0][i] = i;
}
int A, B;
for (int i = 1; i <= e[tour]; i++) {
for (int j = 1; j <= tour - pows[i] + 1; j++) {
A = rmq[i - 1][j]; B = rmq[i - 1][j + pows[i - 1]];
if (depth[A] < depth[B]) {
rmq[i][j] = A;
}
else {
rmq[i][j] = B;
}
}
}
}
int Query(int u, int v) {
int l, r, length, expo, pow, A, B;
l = first[u]; r = first[v];
if (r < l) swap(r, l);
length = r - l + 1;
expo = e[length];
pow = pows[expo];
A = rmq[expo][l]; B = rmq[expo][r - pow + 1];
if (depth[A] < depth[B]) {
return eulerTour[A];
}
return eulerTour[B];
}
int main() {
int u, v;
fin >> n >> m;
for (int i = 2; i <= n; i++) {
fin >> u;
L[u].push_back(i);
}
eulerTour.push_back(-1);
depth.push_back(-1);
EulerTour(1, 0);
tour = eulerTour.size() - 1;
BuildRMQ();
for (int i = 1; i <= m; i++) {
fin >> u >> v;
fout << Query(u, v) << "\n";
}
}