Cod sursa(job #2581281)

Utilizator radustn92Radu Stancu radustn92 Data 14 martie 2020 20:07:30
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.57 kb
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <stack>
#include <vector>
using namespace std;

struct query {
	int to, idx;
};

const int NMAX = 100505;
const int LMAX = 2000505;
int N, queries, values[NMAX], from[NMAX], to[NMAX], eulerIdx;
int ans[LMAX];
vector<int> G[NMAX];
vector<query> queryByNode[NMAX];
vector<int> currPath;

void dfs(int node) {
	from[node] = ++eulerIdx;
	for (auto neighbour : G[node]) {
		dfs(neighbour);
	}
	to[node] = ++eulerIdx;
}

bool inSubtree(int node, int otherNode) {
	return from[node] <= from[otherNode] && to[node] >= to[otherNode];
}

int findLca(int otherNode) {
	int step = 1;
	while (step <= currPath.size()) {
		step *= 2;
	}

	int pos = 0;
	for ( ; step; step >>= 1) {
		if (pos + step < currPath.size() && inSubtree(currPath[pos + step], otherNode)) {
			pos += step;
		}
	}
	return currPath[pos];
}

void dfsQueries(int node) {
	currPath.push_back(node);
	for (auto neighbour : G[node]) {
		dfsQueries(neighbour);
	}

	for (auto& query : queryByNode[node]) {
		ans[query.idx] = findLca(query.to);
	}
	currPath.pop_back();
}

int main() {
	freopen("lca.in", "r", stdin);
	freopen("lca.out", "w", stdout);

	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	cin >> N >> queries;
	int parent;
	for (int node = 2; node <= N; node++) {
		cin >> parent;
		G[parent].push_back(node);
	}

	dfs(1);

	int x, y;
	for (int queryNo = 1; queryNo <= queries; queryNo++) {
		cin >> x >> y;
		queryByNode[x].push_back({y, queryNo});
	}

	dfsQueries(1);
	for (int queryNo = 1; queryNo <= queries; queryNo++) {
		cout << ans[queryNo] << "\n";
	}
	return 0;
}