Cod sursa(job #1350871)

Utilizator ELHoriaHoria Cretescu ELHoria Data 20 februarie 2015 23:51:14
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.28 kb
#include <fstream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;


template<class DataType>
class Rmq {

	function<bool(DataType, DataType)> comp;

	vector<DataType> data;
	vector< vector<size_t> > rmq;
	vector<size_t> lg;

	void build() {
		lg.resize(data.size() + 1);
		for (size_t i = 2; i <= data.size(); i++) {
			lg[i] = lg[i >> 1] + 1;
		}

		size_t rows = lg[data.size()];

		rmq.resize(rows + 1, vector<size_t>(data.size() + 1));
		for (size_t i = 1; i < data.size(); i++) {
			rmq[0][i] = i;
		}

		for (size_t i = 1; i <= rows; i++) {
			for (size_t j = 1; j < data.size() - (1 << i) + 1; j++) {
				rmq[i][j] = comp(data[rmq[i - 1][j]], data[rmq[i - 1][j + (1 << (i - 1))]]) ? rmq[i - 1][j] : rmq[i - 1][j + (1 << (i - 1))];
			}
		}
	}

public:

	Rmq() {}

	Rmq(const vector<DataType>& data_, const function<bool(DataType, DataType)>& comp_) {
		data = data_;
		comp = comp_;
		build();
	}

	size_t queryIndex(size_t l, size_t r) {
		size_t L = lg[r - l + 1];
		return comp(data[rmq[L][l]], data[rmq[L][r - (1 << L) + 1]]) ? rmq[L][l] : rmq[L][r - (1 << L) + 1];
	}

};


class LCA {

		vector< vector<int> > tree;
		vector<int> First, nodes, depth, heights;
		Rmq<int> rmq;
		int k;

		void dfs(int v) {
			First[v] = ++k;
			nodes[k] = v;
			heights[k] = depth[v];
			for (int& w : tree[v]) {
				depth[w] = depth[v] + 1;
				dfs(w);
				nodes[++k] = v;
				heights[k] = depth[v];
			}
		}

	public:

		LCA(int n) {
			tree.resize(n);
			First.resize(n, -1);
			depth.resize(n);
			nodes.resize(2 * n + 1);
			heights = nodes;
			k = 0;
		}

		void build() {
			dfs(0);
			rmq = Rmq<int>(heights, less<int>());
		}

		int query(int x, int y) {
			x = First[x];
			y = First[y];
			if (x > y) swap(x, y);
			return nodes[rmq.queryIndex(x, y)];
		}	

		void addEdge(const int& x, const int& y) {
			tree[x].push_back(y);
		}

};

int main()
{
	ifstream cin("lca.in");
	ofstream cout("lca.out");
	int n, m;
	cin >> n >> m;
	LCA solver(n);
	for (int i = 1; i < n; i++) {
		int v;
		cin >> v;
		solver.addEdge(--v, i);
	}

	solver.build();

	for (int i = 0; i < m; i++) {
		int a, b;
		cin >> a >> b;
		cout << solver.query(--a, --b) + 1 << "\n";
	}
	return 0;
}