Cod sursa(job #1224111)

Utilizator roxana.istratePoenaru Roxana roxana.istrate Data 29 august 2014 18:58:02
Problema Range minimum query Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 2.18 kb
// using RMQ
#include <iostream>
#include <vector>
#include <stack>

using namespace std;

int M[100002][17];

struct NodeItem{
	int parent, height;
	bool once;
	vector<int> kids;
};

typedef struct NodeItem Node;

int n, m, x, a, b;
vector<Node> nodes;
vector<int> et, heights;
vector<int> firstOccur;

void euler_tour(){
	stack<int> st;
	st.push(1);

	while(!st.empty()){
		int nod = st.top(); st.pop();
		et.push_back(nod);
		heights.push_back(nodes[nod].height);
		if(firstOccur[nod] == -1) firstOccur[nod] = heights.size()-1;
		if(nodes[nod].once){
			nodes[nod].once = false;
			for(int i = nodes[nod].kids.size()-1; i >= 0; i--){
				st.push(nod);
				st.push(nodes[nod].kids[i]);
			}
		}
	}
}	

void rmq_init(){
	n = heights.size();
	for(int i = 0; i < 100000; i++){	// todo!
		for(int j = 0; j < 17; j++)
			M[i][j] = 100001;
	}

	for (int i = 0; i < n; i++)
          M[i][0] = i;
	for(int j = 1; (1 << j) <= n; j++){
		for (int i = 0; i + (1 << j) - 1 < n; i++)
              if (heights[M[i][j - 1]] <= heights[M[i + (1 << (j - 1))][j - 1]])
                  M[i][j] = M[i][j - 1];
              else
                  M[i][j] = M[i + (1 << (j - 1))][j - 1];
	}
}

int lg2(int x){
	int cnt = 0;
	while(1 << cnt <= x){
		cnt++;
	}
	return cnt-1;
}

int rmq(int b, int e){
	if(b > e){
		int aux = b;
		b = e;
		e = aux;
	}
	int min_pow = lg2(e-b+1);
	if(heights[M[b][min_pow]] <= heights[M[e-(1 << min_pow)+1][min_pow]]){
		return M[b][min_pow]; 
	}
	return M[e-(1 << min_pow)+1][min_pow];
}

int main(){
	freopen("lca.in", "r", stdin);
	freopen("lca.out", "w", stdout);
	scanf("%d%d", &n, &m);
	Node p; p.once = true;
	//cin >> n >> m;
	for(int i = 0; i <= n ; i++){
		nodes.push_back(p);
		firstOccur.push_back(-1);
	}
	nodes[1].parent = 1;
	nodes[1].height = 0;
	for(int i = 0; i < n - 1; i++){
		scanf("%d", &x);
		//cin >> x;
		nodes[x].kids.push_back(i+2);
		nodes[i+2].parent = x;
		nodes[i+2].height = nodes[x].height + 1;
	}
	euler_tour();

	rmq_init();

	for(int i = 0; i < m; i++){
		scanf("%d%d", &a, &b);
		//cin >> a >> b;
		printf("%d\n", et[rmq(firstOccur[a], firstOccur[b])]);
	}
	return 0;
}