Pagini recente » Monitorul de evaluare | Monitorul de evaluare | Cod sursa (job #2906043) | Monitorul de evaluare | Cod sursa (job #1912056)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#define NMAX 100001
#define LOGMAX 18
#define NE (unsigned)((1<<31) + 1)
using namespace std;
unsigned n, m, maxH = 0, impartire;
unsigned T[NMAX], H[NMAX];
unsigned lg[NMAX];
vector<vector<unsigned>> tatiLog;
unsigned Tsqrt[NMAX];
vector<unsigned> Copchi[NMAX];
unsigned lcaLG(unsigned i, unsigned j) {
if (H[i] < H[j]) {
swap(i, j);
}
for (unsigned k = lg[H[i]]; k > 0 && H[i] != H[j]; --k) {
if (tatiLog[k][i] != NE && H[tatiLog[k][i]] >= H[j]) {
i = tatiLog[k][i];
}
}
//pt k = 0
if (H[tatiLog[0][i]] >= H[j]) {
i = tatiLog[0][i];
}
if (i == j) {
return i + 1;
}
for (unsigned k = lg[H[i]]; k > 0 && T[i] != T[j]; --k) {
if (tatiLog[k][i] != tatiLog[k][j]) {
i = tatiLog[k][i];
j = tatiLog[k][j];
}
}
//pt k = 0
if (tatiLog[0][i] != tatiLog[0][j]) {
i = tatiLog[0][i];
j = tatiLog[0][j];
}
return T[i] + 1;
}
void solveLG() {
unsigned i, j;
// for (unsigned j = 0; (unsigned)(1 << j) <= maxH; ++j) {
// cout << j <<": ";
// for (unsigned i = 0; i < n; ++i) {
// cout<<tatiLog[j][i] << ", ";
// }
// cout<<endl;
// }
while (m--) {
scanf("%d%d", &i, &j);
printf("%d\n", lcaLG(i - 1, j - 1));
}
}
void preprocessLG() {
tatiLog.push_back(vector<unsigned>(n));
tatiLog[0][0] = NE;
for (unsigned i = 1; i < n; ++i) {
tatiLog[0][i] = T[i];
}
for (unsigned j = 1; (unsigned)(1 << j) <= maxH; ++j) {
tatiLog.push_back(vector<unsigned>(n, NE));
for (unsigned i = 0; i < n; ++i) {
if (tatiLog[j-1][i] != NE) { // echivalent cu H[i] - (1<<(j-1)) >= 0
tatiLog[j][i] = tatiLog[j-1][tatiLog[j-1][i]];
}
}
}
lg[0] = 0;
lg[1] = 0;
for (unsigned i = 2; i <= maxH; ++i) {
lg[i] = lg[i >> 1] + 1;
}
}
unsigned lcaSQRT(unsigned i, unsigned j) {
while (Tsqrt[i] != Tsqrt[j]) {
if (H[i] > H[j]) {
i = Tsqrt[i];
} else {
j = Tsqrt[j];
}
}
while (i != j) {
if (H[i] > H[j]) {
i = T[i];
} else {
j = T[j];
}
}
return i + 1;
}
void solveSQRT() {
unsigned i, j;
while (m--) {
scanf("%d%d", &i, &j);
printf("%d\n", lcaSQRT(i - 1, j - 1));
}
}
void preprocessSQRT() {
for (unsigned i = 0; i < n; ++i) {
unsigned lev = H[i] / impartire;
unsigned tatal = T[i];
lev = lev < 1 ? lev : lev - 1;
while (H[tatal] / impartire != lev) {
tatal = T[tatal];
}
Tsqrt[i] = tatal;
}
}
void dfsSQRT(unsigned nod, unsigned tatal) {
if (!(H[nod] % impartire)) {
tatal = T[nod];
}
Tsqrt[nod] = tatal;
for (auto it : Copchi[nod]) {
dfsSQRT(it, tatal);
}
}
unsigned inaltime(unsigned nod) {
if (nod == 0) {
return 0;
}
if (!H[T[nod]]) {
return inaltime(T[nod]) + 1;
}
return H[T[nod]] + 1;
}
void inaltime() {
for (unsigned i = 0; i < n; ++i) {
H[i] = inaltime(i);
maxH = max(maxH, H[i]);
}
impartire = sqrt(maxH);
}
void read() {
unsigned tatal;
scanf("%d%d", &n, &m);
T[0] = 0;
H[0] = 0;
for (unsigned i = 1; i < n; ++i) {
scanf("%d", &tatal);
--tatal;
T[i] = tatal;
//Copchi[tatal].push_back(i);
}
}
int main()
{
freopen("lca.in", "r", stdin);
freopen("lca.out", "w", stdout);
read();
inaltime();
preprocessSQRT();
//dfsSQRT(0, 0);
solveSQRT();
//preprocessLG();
//solveLG();
return 0;
}