Cod sursa(job #1198251)

Utilizator howsiweiHow Si Wei howsiwei Data 15 iunie 2014 08:30:09
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.37 kb
#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
using namespace std;

vector<vector<int>> adjl;
vector<int> path;
vector<int> index;
vector<int> level;
vector<vector<int>> table;

void build_euler_path(int u, int lvl)
{
	level[u] = lvl;
	index[u] = path.size();
	path.push_back(u);
	for (auto v: adjl[u]) {
		build_euler_path(v, lvl+1);
		path.push_back(u);
	}
}

int highest(int u, int v)
{
	return level[u] <= level[v] ? u : v;
}

void build_table()
{
	int size = log2(path.size()-1)+1;
	table.resize(size);
	table[0] = path;
	for (int i = 1; i < size; i++) {
		int stp = 1<<i;
		table[i].resize(path.size()-stp);
		for (int j = table[i].size()-1; j >= 0; j--) {
			table[i][j] = highest(table[i-1][j], table[i-1][j+stp/2]);
		}
	}
}

int lca(int u, int v)
{
	if (u == v) {
		return u;
	}
	int x = min(index[u], index[v]);
	int y = max(index[u], index[v]);
	int lg = log2(y-x);
	return highest(table[lg][x], table[lg][y-(1<<lg)+1]);
}

int main()
{
	ios::sync_with_stdio(false);
	freopen("lca.in", "r", stdin);
	freopen("lca.out", "w", stdout);
	int n, m;
	cin >> n >> m;
	adjl.resize(n);
	for (int i = 1; i < n; i++) {
		int p;
		cin >> p;
		p--;
		adjl[p].push_back(i);
	}
	index.resize(n);
	level.resize(n);
	build_euler_path(0, 0);
	build_table();
	for (int i = 0; i < m; i++) {
		int u, v;
		cin >> u >> v;
		u--, v--;
		printf("%d\n", lca(u, v)+1);
	}
	return 0;
}