Cod sursa(job #1420522)

Utilizator Dddarius95Darius-Florentin Neatu Dddarius95 Data 18 aprilie 2015 16:55:21
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.95 kb
// LCA - O(NlogN+M)
// LCA(x,y)este nodul de nivel minim intre primele aparitii
// ale nodurilor x si y in reprezentarea Euler a arborelui
#include <fstream>
#include <vector>
#include <bitset>
#define Nmax 100099
#define Emax 200099
#define LgMax 18
using namespace std;
ifstream f("lca.in");
ofstream g("lca.out");


int N, M;
vector < int > G[Nmax];
bitset < Nmax > viz;

/* E parcurgere Euler, Level[node] nivelul lui node
  First[node] = prima aparitie a lui node in E[] */
int E[Emax], Level[Nmax], First[Nmax];

int lg[Emax],RMQ[LgMax][Emax],x,y;

/* Voi face o parcugere DSF si voi pune node la inceput si  dupa fiecare fiu */
void DFS(const int& node, const int& level) {
     viz[node] = 1;
     E[ ++E[0] ] = node;
     First[node]=E[0];
     Level[node] = level;
     for(vector<int>::iterator it = G[node].begin(); it != G[node].end(); ++it)
          if(!viz[*it]) {
            DFS(*it,level+1);
            E[++E[0]]=node;
          }
}

void buildRMQ() {

 for(int i = 2; i <= E[0]; ++i) lg[i] = lg[i/2] + 1;

 for(int j = 1; j <= E[0]; ++j) RMQ[0][j] = E[j];

 for(int i = 1; (1<<i) <= E[0]; ++i)
      for(int j = 1; j <= E[0]-(1<<i)+1; ++j)
      {
           int x = RMQ[i-1][j] , y = RMQ[i-1][j+(1<<(i-1))];
           if(Level[x]<Level[y])RMQ[i][j]=x;
                           else RMQ[i][j]=y;
      }
}

int LCA(const int& x, const int& y) {
     int st = First[x], dr = First[y];
     if(st > dr) swap(st,dr);

     int i = lg[dr-st+1];
     int x1=RMQ[i][st], x2 = RMQ[i][dr-(1<<i)+1];
     if(Level[x1]<Level[x2])return x1;
                       else return x2;
}




int main()
{
   f >> N >> M;
   for(int i = 2; i <= N; ++i)
        f >> x , G[x].push_back(i); /*ATENTIE citire speciala infoarena! */

   DFS(1,1); /* parcurgere eulere */

   buildRMQ();
   for(int i=1;i<=M;++i) {
        f >> x >> y;
        g << LCA(x,y) << '\n';
   }
   f.close();g.close();
   return 0;
}