Cod sursa(job #2500791)

Utilizator mihnea00Duican Mihnea mihnea00 Data 28 noiembrie 2019 18:12:12
Problema Lowest Common Ancestor Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.45 kb
#include <iostream>
#include <fstream>
#include <vector>

#define INF 0x3f3f3f3f

	std::ifstream fin("lca.in");
	std::ofstream fout("lca.out");

void mySwap (int &a, int &b) {
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;
}

void recursiveDfs (int &node, int &level, std::vector<int> &eulerRep,
	std::vector<int> &levelEvidence, int *firstOccourance,
	std::vector<std::vector<int>> &graph, int &fromNode) {

	eulerRep.push_back(node);
	levelEvidence.push_back(level);
	firstOccourance[node] = eulerRep.size() - 1;

	for (int i = 0; i < graph[node].size(); ++i) {
		if (graph[node][i] == fromNode)
			continue;

		int nextLevel = level + 1;
		recursiveDfs(graph[node][i], nextLevel, eulerRep, levelEvidence,
			firstOccourance, graph, node);

		eulerRep.push_back(node);
		levelEvidence.push_back(level);
	}
}


void makeSegmentTree(int &node, int &left, int &right,
	int *segmentTree, std::vector<int> &levelEvidence) {

	if (left == right) {
		segmentTree[node] = left;

		// std::cout << node;
		// std::cout << "\n";
		// return;
	} else {
		int mijl = ((left + right) >> 1);
		int nodeLeft = (node << 1);
		int nodeRight = ((node << 1) + 1);

		// std::cout << node << " -> " << nodeLeft << " si " << nodeRight;
		// std::cout << "\n";

		makeSegmentTree(nodeLeft, left, mijl, segmentTree, levelEvidence);
		++mijl;
		makeSegmentTree(nodeRight, mijl, right, segmentTree, levelEvidence);

		if (levelEvidence[segmentTree[nodeLeft]] <=
			levelEvidence[segmentTree[nodeRight]]) {
			segmentTree[node] = segmentTree[nodeLeft];
		} else {
			segmentTree[node] = segmentTree[nodeRight];
		}
	}
}

void querryLca(int &node, int &left, int &right,
	int *segmentTree, std::vector<int> &levelEvidence, std::vector<int> &eulerRep,
	int &sol, int &solH, int &nodeLeft, int &nodeRight) {

	if (nodeLeft <= left && right <= nodeRight) {


			// 123523
		if (levelEvidence[segmentTree[node]] < solH) {
			// fout << node << "\n";
			// 46292
			sol = eulerRep[segmentTree[node]];
			solH = levelEvidence[segmentTree[node]];
		}
		// return sol;
	} else {

		int mijl = ((left + right) >> 1);
		int nodeL = (node << 1);
		int nodeR = ((node << 1) + 1);

		if (nodeLeft <= mijl)
			querryLca(nodeL, left, mijl, segmentTree, levelEvidence, eulerRep,
				sol, solH, nodeLeft, nodeRight);
		++mijl;
		if (mijl <= nodeRight)
			querryLca(nodeR, mijl, right, segmentTree, levelEvidence, eulerRep,
				sol, solH, nodeLeft, nodeRight);
		
	}
}

std::vector<int> lca(std::vector<std::vector<int>> &graph,
	std::vector< std::pair<int, int> > &queries) {

	std::vector<int> eulerRep, levelEvidence, ans;
	eulerRep.push_back(0);
	levelEvidence.push_back(0);
	int *firstOccourance;
	int node = 1, level = 0, **rmq, *lg;
	int left = 1;

	firstOccourance = new int [graph.size() + 2];

	recursiveDfs(node, level, eulerRep, levelEvidence, firstOccourance, graph, level);

	int *segmentTree;
	segmentTree = new int [levelEvidence.size() * 4] {0};

	int right = levelEvidence.size() - 1;

	makeSegmentTree(node, left, right, segmentTree, levelEvidence);
	// segmentTree[1] = 1;
	

	for (int i = 0; i < queries.size(); ++i) {
		
		int nodeL = firstOccourance[queries[i].first];
		int nodeR = firstOccourance[queries[i].second];

		if (nodeL > nodeR)
			mySwap(nodeL, nodeR);
		int sol = INF;
		int solH = INF;
		
		querryLca(node, left, right, segmentTree, levelEvidence, eulerRep,
			sol, solH, nodeL, nodeR);

		ans.push_back(sol);
	}

	// for (int i = 0; i < eulerRep.size() * 3; ++i) {
	// 	fout << segmentTree[i] << "\n";
	// }
	// std::cout << "peste\n";

	// std::cout << "\n";

	

	// for (int i = 0; i < eulerRep.size(); ++i) {
	// 	std::cout << i << " -> " << levelEvidence[i] << " \n";
	// }
	// std::cout << "\n";

	// for (int i = 0; i < eulerRep.size(); ++i) {
	// 	std::cout << i << " -> " << eulerRep[i] << " \n";
	// }
	// std::cout << "\n";


	delete [] firstOccourance;
	delete [] segmentTree;
	return ans;

}

int main () {


	int n, m, node1, node2;
	std::vector< std::vector<int> > graph;
	std::vector< std::pair<int, int> > queries;


	fin >> n >> m; // number of nodes and queries
	graph.resize(n + 1);

	for (int i = 2; i <= n; ++i) {
        fin >> node1;
        graph[node1].push_back(i);
        graph[i].push_back(node1);

		// fin >> node1 >> node2;
  //       graph[node1].push_back(node2);
  //       graph[node2].push_back(node1);
	}

	for (int i = 0; i < m; ++i) {
        fin >> node1 >> node2;
		queries.push_back({node1, node2});
	}

	std::vector<int> ans = lca(graph, queries);

	for (int i = 0; i < ans.size(); ++i) {
		fout << ans[i] << "\n";
	}

	return 0;
}