Cod sursa(job #1067506)

Utilizator cosmo0093Raduta Cosmin cosmo0093 Data 26 decembrie 2013 22:19:04
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.27 kb
#include <fstream>
#include <utility>
#include <vector>
#include <climits>

class LCA {
	struct Vertex {
		int apar;
		std::vector<int> myL;
		Vertex() : apar(-1), myL() {}
	};
	struct Euler {
		int node, lvl;
		Euler() : node(), lvl() {}
		Euler(int a, int b) : node(a), lvl(b) {}
	};
	int nV, back, *log, **RMQ;
	Vertex *myG;
	Euler *myV;
	void dfa(int nod, int level) {
		myV[++back] = Euler(nod, level);
		myG[nod].apar = back;
		for(auto it = myG[nod].myL.begin(); it != myG[nod].myL.end(); it++) {
			dfa(*it, level + 1);
			myV[++back] = Euler(nod, level);
		}
	}  
public:
	LCA(int a) : nV(a), back(), myG(new Vertex[a + 1]), myV(new Euler[a << 1]) {
		myV[0] = Euler(INT_MAX, INT_MAX);
		for(int i = 0; i <= a; i++) {
			myG[i] = Vertex();
		}
	}
	~LCA() {
		delete[] myG;
		delete[] myV;
		delete[] log;
		for(int i = 0; i <= back; i++) {
			delete[] RMQ[i];
		}
		delete[] RMQ;
	}
	void pushEdge(int a, int b) {
		myG[a].myL.push_back(b);
	}
	void start() {
		dfa(1, 0);
		log = new int[back + 1];
		log[1] = 0;
		for(int i = 2; i <= back; i++) {
			log[i] = log[i >> 1] + 1;
		}
		RMQ = new int*[back + 1];
		for(int i = 0; i <= back; i++) {
			RMQ[i] = new int[log[back] + 1];
		}
		for(int i = 0; i <= back; i++) {
			for(int j = 0; j <= log[back]; j++) {
				RMQ[i][j] = 0;
			}
		}
		for(int i = 1; i <= back; i++) {
			RMQ[i][0] = i;
		}
		for(int j = 1; (1 << j) <= back; j++) {
			for(int i = 1; i + (1 << j) - 1 <= back; i++) {
				int aux = 1 << (j - 1);
				if(myV[RMQ[i][j - 1]].lvl > myV[RMQ[i + aux][j - 1]].lvl) {
					RMQ[i][j] = RMQ[i + aux][j - 1];
				} else {
					RMQ[i][j] = RMQ[i][j - 1];
				}
			}		
		}
	}
	int query(int x, int y) {
		int a = myG[x].apar, b = myG[y].apar;
		if(a > b) {
	 		return query(y, x);
		}
		int aux = b - a + 1;
		int loga = log[aux];		
		int search = aux - (1 << loga);
		int sol;
		if(myV[RMQ[a][loga]].lvl > myV[RMQ[a + search][loga]].lvl) {
			sol = myV[RMQ[a + search][loga]].node;
		} else {
			sol = myV[RMQ[a][loga]].node;
		}
		return sol;
	}
};

int main() {
	std::ifstream in("lca.in");
	std::ofstream out("lca.out");
	int nV, nOp, x, y;
	in >> nV >> nOp;
	LCA a(nV);
	for(int i = 2; i <= nV; i++) {
		in >> x;
		a.pushEdge(x, i);
	}
	a.start();
	for(int i = 0; i < nOp; i++) {
		in >> x >> y;
		out << a.query(x, y) << '\n';
	}
	return 0;
}