Pagini recente » Cod sursa (job #3040211) | Cod sursa (job #1898531) | Cod sursa (job #3277494) | Cod sursa (job #1862940) | Cod sursa (job #1670031)
# include <cstdio>
# include <vector>
using namespace std;
FILE *f = freopen("lca.in", "r", stdin);
FILE *g = freopen("lca.out", "w", stdout);
const int N_MAX = 100001;
int father[N_MAX];
int H[2 * N_MAX]; /// parcurgere euleriana
int first[N_MAX]; /// pozitia unde l-am gasit prima data
int niv[2 * N_MAX]; /// nivelul din arbore al nodului de pe pozitia i din parcurgere
int lg[2 * N_MAX];
int rmq[20][N_MAX];
int n, m;
int k;
vector <int> G[N_MAX];
void read()
{
scanf("%d %d", &n, &m);
for (int i=2; i<=n; i++)
{
scanf("%d", &father[i]);
G[father[i]].push_back(i);
}
}
void parc_euler(int nod = 1, int nivel = 0)
{
H[++k] = nod;
first[nod] = k;
niv[k] = nivel;
for (int i : G[nod])
{
if (!first[i]) /// nu a fost vizitat
parc_euler(i, nivel + 1);
H[++k] = nod;
niv[k] = nivel;
}
}
void init_rmq()
{
for (int i=2; i<=k; i++)
lg[i]= lg[i/2] + 1;
for (int i = 1; i<=k; i++)
rmq[0][i] = i; /// rmq reprezinta nodul din parc euleriana care are cel mai
/// mic nivel de la poz j la poz j + 2^i - 1;
for (int i = 1; (1 << i) <= k; i++)
{
int put = (1 << (i-1));
for (int j=1; j<= k - (1<<i) + 1; j++)
{
rmq[i][j] = rmq[i-1][j];
if (niv[rmq[i-1][j]] > niv[rmq[i-1][j + put]])
rmq[i][j] = rmq[i-1][j + put];
}
}
}
int lca(int x, int y)
{
int first_x = first[x];
int first_y = first[y];
if (first_x > first_y)
swap(first_x, first_y);
int diff = first_y - first_x + 1;
int log = lg[diff];
int put = 1<<log;
int ans = rmq[log][first_x];
if (niv[rmq[log][first_x]] > niv[rmq[log][first_y - put + 1]])
ans = rmq[log][first_y - put + 1];
return H[ans];
}
void query()
{
for (int i=1; i<=m; i++)
{
int x, y;
scanf("%d %d", &x, &y);
printf("%d\n", lca(x, y));
}
}
int main()
{
read();
parc_euler();
init_rmq();
query();
return 0;
}