Cod sursa(job #2497640)

Utilizator lucian2015blaugranadevil lucian2015 Data 23 noiembrie 2019 02:03:45
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.71 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <stdlib.h>
using namespace std;

ifstream f("lca.in");
ofstream g("lca.out");


class lcaSegmentTrees{
private:
	vector<vector<int> > graph;
	vector<int> eulerAp;
	vector<int> heights;
	vector<int> firstApInEuler;
	vector<int> segmenttree;
	vector<int> visited;

public:
	lcaSegmentTrees( vector<vector<int > > mygraph){
		graph = mygraph;
		eulerAp.reserve(2*graph.size());
		heights.resize(graph.size(),0);
		visited.resize(graph.size(),0);
		firstApInEuler.resize(graph.size(),0);
		dfs(1,0);
		segmenttree.resize(4*eulerAp.size(),0);
	}
	void dfs(int nod, int height){
		visited[nod] = 1;
		heights[nod] = height;
		firstApInEuler[nod] = eulerAp.size();
		eulerAp.push_back(nod);
		for( auto it : graph[nod]){
			if(!visited[it]){
			dfs( it, height + 1);
			eulerAp.push_back(nod);
		}
	}
	}
	  int query(int node, int b, int e, int L, int R) {
        if (b > R || e < L)
            return -1;
        if (b >= L && e <= R)
            return segmenttree[node];
        int mid = (b + e) >> 1;

        int left = query(node << 1, b, mid, L, R);
        int right = query(node << 1 | 1, mid + 1, e, L, R);
        if (left == -1) return right;
        if (right == -1) return left;
        return heights[left] < heights[right] ? left : right;
    }
	 void buildsegmenttree(int nod, int b, int e) {
        if (b == e) {
            segmenttree[nod] = eulerAp[b];
        } else {
            int mid = (b + e) / 2;
            buildsegmenttree(nod << 1, b, mid);
            buildsegmenttree(nod << 1 | 1, mid + 1, e);
            int l = segmenttree[nod << 1], r = segmenttree[nod << 1 | 1];
            segmenttree[nod] = (heights[l] < heights[r]) ? l : r;
        }
    }
    int resolve( int x, int y){
    	int st = firstApInEuler[x];
    	int dr = firstApInEuler[y];
    //	g <<" da " <<st <<" "<<dr<<"\n";
    	if( st < dr )
    		swap(x,y);
    	if( st - dr == 1)
    		return st;
    	return query( 1, 0, eulerAp.size() - 1, st, dr);

    }
	void getlca(vector< pair<int,int> >& queries ){
       buildsegmenttree(1, 0, eulerAp.size() - 1 );
       for( auto it : queries){
       	// g << firstApInEuler[it.first] <<" " << firstApInEuler[it.second]<<"\n";
       	  g << resolve(it.first, it.second) <<"\n";
       }
	}

};


void lca( vector<vector<int> >& graph, vector< pair<int,int> >& queries ){
	lcaSegmentTrees mylca(graph);
	mylca.getlca(queries);
}

int main(){
int x, nod, y, n, m;
vector< pair< int, int > > queries;
f >> n >> m;
vector<int> parents(n + 1, 0);
vector< vector < int> > graph(n + 1);
for( int i = 2; i <=  n; i++){
	f >> parents[i];
  graph[parents[i]].push_back(i);
}
for( int i = 1; i <= m; i++ ){
	f >> x >> y;
	queries.push_back({x,y});
 }
 lca(graph,queries);

}