Pagini recente » Cod sursa (job #1044230) | Cod sursa (job #2339803) | Cod sursa (job #386209) | Cod sursa (job #2490539) | Cod sursa (job #3173781)
#include <fstream>
#include <vector>
#include <list>
#include <cmath>
using namespace std;
ifstream cin("lca.in");
ofstream cout("lca.out");
int num_nodes, queries;
list<int> links[100002];
int f_app[100002];
pair<int, int> et[200002]; int pos = 1;
pair<int, int> rmq[18][100002];
void euler_tour(int node, int grade);
int range_minimum_query(int node1, int node2);
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cin >> num_nodes >> queries;
for(int i = 2 ; i <= num_nodes; i++) {
int node;
cin >> node;
links[node].push_back(i);
}
//euler tour using dfs
euler_tour(1, 0);
pos--;
//test: show the euler euler tour
/*
for(int i = 1; i <= pos; i++) {
cout << et[i].first << ' ';
}
cout << '\n';
for(int i = 1; i <= pos; i++) {
cout << et[i].second << ' ';
}
cout << '\n' << '\n';
*/
//test: show f_app
/*
for(int i = 1; i <= num_nodes; i++) {
cout << f_app[i] << ' ';
}
cout << '\n' << '\n';
*/
//form the range minimum query
for(int i = 1; i <= pos; i++) {
rmq[0][i].first = et[i].first;
rmq[0][i].second = et[i].second;
}
for(int i = 2; i <= pos; i *= 2) {
for(int j = 1; j <= pos - i + 1; j++) {
//.second will be the minimum between the 2 pairs above
//.first will be the grade of the number selected
int line = log2(i);
if(rmq[line - 1][j].second < rmq[line - 1][j + i / 2].second) {
rmq[line][j].first = rmq[line - 1][j].first;
rmq[line][j].second = rmq[line - 1][j].second;
}
else {
rmq[line][j].first = rmq[line - 1][j + i / 2].first;
rmq[line][j].second = rmq[line - 1][j + i / 2].second;
}
}
}
//test: show the rmq
/*
for(int i = 0; i <= log2(pos); i++) {
for(int j = 1; j <= pos - (1 << i) + 1; j++) {
cout << rmq[i][j].first << ' ';
}
cout << '\n';
}
cout << '\n';
*/
//answer the queries
while(queries--) {
int node1, node2;
cin >> node1 >> node2;
cout << range_minimum_query(min(f_app[node1], f_app[node2]), max(f_app[node1], f_app[node2])) << '\n';
}
return 0;
}
void euler_tour(int node, int grade) {
et[pos].first = node;
et[pos].second = grade;
pos++;
if(f_app[node] == 0) {
f_app[node] = pos - 1;
}
for(auto link : links[node]) {
euler_tour(link, grade + 1);
et[pos].first = node;
et[pos].second = grade;
pos++;
}
}
int range_minimum_query(int app_node1, int app_node2) {
pair<int, int> ans = make_pair(-1, -1); int crt = app_node1;
int length = app_node2 - app_node1 + 1;
//return length;
for(int i = 0; i <= log2(length); i++) {
if(length & (1 << i)) {
if(ans == make_pair(-1, -1)) {
ans = rmq[i][crt];
}
else {
if(rmq[i][crt].second < ans.second) {
ans = rmq[i][crt];
}
}
//cout << length << ' ' << (1 << i) << '\n';
crt += (1 << i);
}
}
return ans.first;
}