Pagini recente » Cod sursa (job #2391325) | Cod sursa (job #1771235) | Cod sursa (job #322437) | Cod sursa (job #1186054) | Cod sursa (job #2877153)
#include <fstream>
#include <vector>
using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");
//Implementare cu Arbori de Intervale ~= 70p;
#define DIM 100000
#define INF (1LL << 30)
int n, m, k;
int ap[DIM + 1]; //prima aparitie a nodului fiecarui nod in reprezentarea euler;
int Euler[DIM * 2 + 1];
int tree[DIM * 8 + 5];
int nivel[DIM * 2 + 1];
vector <int> G[DIM + 1];
static inline void Build(int st, int dr, int nod) {
if(st == dr)
tree[nod] = st; //retin indicele elementelor;
else {
int mid = (st + dr) / 2;
Build(st, mid, nod * 2);
Build(mid + 1, dr, nod * 2 + 1);
if(nivel[tree[nod * 2]] < nivel[tree[nod * 2 + 1]])
tree[nod] = tree[nod * 2];
else tree[nod] = tree[nod * 2 + 1];
}
}
static inline int Query(int st, int dr, int nod, int left, int right) {
int min1 = 0, min2 = 0;
if(left <= st && dr <= right)
return tree[nod];
int mid = (st + dr) >> 1;
if(left <= mid)
min1 = Query(st, mid, nod * 2, left, right);
if(mid < right)
min2 = Query(mid + 1, dr, nod * 2 + 1, left, right);
if(nivel[min1] < nivel[min2])
return min1;
return min2;
}
static inline void dfs(int nod, int lvl) {
Euler[++k] = nod;
nivel[k] = lvl;
ap[nod] = k;
for(auto e : G[nod]) {
dfs(e, lvl + 1);
Euler[++k] = nod;
nivel[k] = lvl;
}
}
static inline int lca(int x, int y) {
if(x > y)
swap(x, y);
int nod = Query(1, k, 1, ap[x], ap[y]); //caut nivelul minim intre prima aparitie a lui x si y;
return Euler[nod];
}
int main() {
fin.tie(0);
fout.tie(0);
fin >> n >> m;
for(int i = 2; i <= n; i++) {
int x;
fin >> x;
G[x].push_back(i);
}
nivel[0] = INF; //santinela;
k = 0; //numarul de noduri din parcurgerea euleriana;
dfs(1, 0);
Build(1, k, 1);
int x, y;
for(int i = 1; i <= m; i++) {
fin >> x >> y;
fout << lca(x, y) << '\n';
}
return 0;
}