Pagini recente » Cod sursa (job #375768) | Cod sursa (job #2137965) | Cod sursa (job #2479776) | Cod sursa (job #687951) | Cod sursa (job #2606508)
#include <stdio.h>
#include <bits/stdc++.h>
#define rep(i, n) for(int i = 0; i < (int)(n); i++)
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
const int INF = 0x3f3f3f3f;
ifstream fin ("lca.in");
ofstream fout ("lca.out");
const int Nmax = 100555;
vi Cop[Nmax]; // for each vertex keeps a list of children
vi Epath; // vertices in the Euler path
vi Lvl; // corresponding level of the vertex in the Euler path; // will run RMQ on Lvl
vi H(Nmax, -1); // where in the euler path is the first occurence of a given vertex;
void dfs(int nod, int lvl) {
if (H[nod] == -1) { H[nod] = Epath.size(); }
Epath.push_back(nod);
Lvl.push_back(lvl);
for(auto c: Cop[nod]) {
dfs(c, lvl+1);
Epath.push_back(nod);
Lvl.push_back(lvl);
}
}
int main(void) {
// freopen("lca.in", "r", stdin);
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
int N, M, a, b;
fin >> N >> M;
for(int i = 1; i < N; i++) {
fin >> a;
--a;
Cop[a].push_back(i);
}
// dfs to construct the Euler representation on which we will be running rmq;
dfs(0, 0);
// cout << Epath.size() << " " << Lvl.size() << endl;
// for(auto e: Epath) { cout << e+1 << ' '; } cout << endl;
// for(auto l: Lvl) { cout << l << ' '; } cout << endl;
// for(int i = 0; i < N; i++) {
// cout << i << ":\t" << H[i] << endl;
// }
// pre-process rmq;
int rmqN = Lvl.size();
vi lg(rmqN+1, 0);
for(int n = 2; n <= rmqN; n++) { lg[n] = lg[n/2] + 1; }
// cout << string(40, '-') << "lg[]" << string(40, '-') << endl;
// rep(i, rmqN+1) { cout << lg[i] << " "; } cout << endl;
vector<vi> rmq(lg[rmqN]+1, vi(rmqN));
rep(i, rmqN) {
rmq[0][i] = i;
}
for(int l = 1; l <= lg[rmqN]; l++) {
for(int i = 0; i + (1 << l) - 1 < rmqN; i++) {
int rmq_left = rmq[l-1][i];
int rmq_right = rmq[l-1][i + (1<<(l-1))];
if (Lvl[rmq_left] <= Lvl[rmq_right]) {
rmq[l][i] = rmq_left;
} else {
rmq[l][i] = rmq_right;
}
}
}
// for(int l = 0; l <= lg[rmqN]; l++) {
// cout << string(40, '-') << "l:\t" << l << string(40, '-') << endl;
// rep(i, N) {
// cout << rmq[l][i] << " ";
// }
// cout << endl;
// rep(i, N) {
// cout << Lvl[rmq[l][i]] << " ";
// }
// cout << endl;
// }
// read and execute the queries
rep(i, M) {
fin >> a >> b;
// cout << string(40, '-') << "case:\t" << i << string(40, '-') << endl;
// cout << a << " " << b << endl;
--a, --b;
int x = H[a];
int y = H[b];
// cout << x << " " << y << endl;
if (x > y) { swap(x, y); }
int l = lg[y-x+1];
int rmq_left = rmq[l][x];
int rmq_right = rmq[l][y-(1<<l)+1];
// cout << rmq_left << " " << rmq_right << endl;
// cout << Lvl[rmq_left] << " " << Lvl[rmq_right] << endl;
int lca_pos = -1;
if (Lvl[rmq_left] <= Lvl[rmq_right]) {
lca_pos = rmq_left;
} else {
lca_pos = rmq_right;
}
fout << Epath[lca_pos] + 1 << '\n';
}
return 0;
}