Cod sursa(job #1428695)

Utilizator DuxarFII-Stefan-Negrus Duxar Data 4 mai 2015 22:17:17
Problema Lowest Common Ancestor Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 2.62 kb
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <vector>
 
using namespace std;
 
#define NMAX (100000 << 1)
 
int N, M, pos_euler = 1;
 
vector <int> euler_nodes(NMAX), level(NMAX), biggest_power2, first_found(NMAX);
vector <vector <int> > rmq, graph;
 
void EulerDfs(int iam, int c_level);
void PrepareRMQ();
 
int main() {
#ifdef INFOARENA
	    freopen("lca.in", "r", stdin);
	    freopen("lca.out", "w", stdout);
#else
	    freopen("input.cpp", "r", stdin);
#endif
	     
	    int i, x, y, lg, p2, px, py, ans;
	     
	    scanf("%d %d", &N, &M);
	    graph.resize(N + 1);
	    for (i = 2; i <= N; ++i) {
		        scanf("%d", &x);
		        graph[x].push_back(i);
		    }
	     
	    EulerDfs(1, 0);
	    PrepareRMQ();
	     
	    for (i = 1; i <= M; ++i) {
		        scanf("%d %d", &x, &y);
		        px = first_found[x];
		        py = first_found[y];
		        if (py < px) {
			            swap(px, py);
			        }
		        lg = py - px + 1;
		        p2 = biggest_power2[lg];
		        ans = rmq[p2][px];
		        if (level[rmq[p2][py - (1 << p2) + 1]] < level[ans]) {
			            ans = rmq[p2][py - (1 << p2) + 1];
			        }
		        printf("%d\n", euler_nodes[ans]);
		    }
	     
	     
	    return 0;
}
 
void EulerDfs(int iam, int c_level) {
	    euler_nodes[pos_euler] = iam;
	    level[pos_euler] = c_level;
	    first_found[iam] = pos_euler;
	    ++pos_euler;
	     
	    for (auto to: graph[iam]) {
		        EulerDfs(to, c_level + 1);
		        euler_nodes[pos_euler] = iam;
		        level[pos_euler] = c_level;
		        ++pos_euler;
		    }
}
 
void PrepareRMQ() {
	 
	    biggest_power2.resize(pos_euler, 0);
	    rmq.resize(19, vector <int> (pos_euler, 0));
	    --pos_euler;
	     
	    int i, k, lg;
	     
	    rmq[0][1] = 1;
	    for (i = 2; i <= pos_euler; ++i) {
		        biggest_power2[i] = biggest_power2[i >> 1] + 1;
		        rmq[0][i] = i;
		    }
	     
	    for (k = 1; (1 << k) <= pos_euler; ++k) {
		        lg = 1 << (k - 1);
		        for (i = 1; i + (1 << k) - 1 <= pos_euler; ++i) {
			            rmq[k][i] = rmq[k - 1][i];
			            if (level[rmq[k - 1][i + lg]] < level[rmq[k][i]]) {
				                rmq[k][i] = rmq[k - 1][i + lg];
				            }
			        }
		    }
}