Cod sursa(job #2501078)

Utilizator lucian2015blaugranadevil lucian2015 Data 29 noiembrie 2019 02:55:38
Problema Lowest Common Ancestor Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.18 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <stdlib.h>
    
#define INF 0x3f3f3f3f
    
#define MAX_N 100005
    
#define nst (nod << 1)
#define ndr (nst | 1)
#define mij ((superiorlimit + inferiorlimit) >> 1)
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;
    int eulerpoz = 0;
    int solution = INF;
    int heightsolution = INF;
    int left ;
    int right ;

public:
	lcaSegmentTrees( vector<vector<int > > mygraph){
		graph = mygraph;
		eulerAp.resize(mygraph.size()*4  ,0);
    firstApInEuler.resize(mygraph.size()*4 ,0 );
    heights.resize(mygraph.size()*4 ,0);
    segmenttree.resize(mygraph.size()*4,0);

	}
	void dfs(int nod, int height){
		eulerAp[++eulerpoz] = nod;
        heights[eulerpoz] = height;
        firstApInEuler[nod] = eulerpoz;
        for( auto it :graph[nod]){
            dfs(it,height + 1);
            eulerAp[++eulerpoz] = nod; // in intoarcerea din dfs se  mai viziteaza nodul
            heights[eulerpoz] = height;
        }
	}
	
	 void buildsegmenttree(int nod, int inferiorlimit, int superiorlimit ) {
        if( inferiorlimit == superiorlimit ){
  
            segmenttree[nod] = inferiorlimit;
            return;
        }
            buildsegmenttree( nst, inferiorlimit, mij );
            buildsegmenttree( ndr , mij + 1, superiorlimit );
        if( heights[segmenttree[nst]] <= heights[segmenttree[ndr]] ){
            segmenttree[nod] = segmenttree[nst];
             //g << segmenttree[nod] <<" "<<"da";
        }
       else{
           segmenttree[nod] = segmenttree[ndr];
        }

    }
    void query(int nod, int inferiorlimit, int superiorlimit ) {
      if( left <= inferiorlimit && superiorlimit <= right ){
        if( heights[segmenttree[nod]] < heightsolution )
            solution = eulerAp[segmenttree[nod]],
           heightsolution = heights[segmenttree[nod]];
       
           return;
      }
      if( left <= mij ) 
        query( nst, inferiorlimit, mij);
       if( mij < right)
         query( ndr, mij + 1, superiorlimit);

    }
    int resolve( int x, int y){
    	left = firstApInEuler[x];
    	right = firstApInEuler[y];
    if( left > right )
    	swap(left,right);
        solution = INF;
        heightsolution = INF;
        query(1,1,eulerpoz);
      return solution;
    }
	void getlca(vector< pair<int,int> >& queries ){
        dfs(1,0);
       // for(int i = 1; i <= eulerpoz; i++)
       //     g << heights[i] <<" ";
        buildsegmenttree(1,1,eulerpoz);
      //  g<<"\n";
       for( auto it : queries ){
            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);

}