Cod sursa(job #1147820)

Utilizator thebest001Neagu Rares Florian thebest001 Data 20 martie 2014 10:20:08
Problema Lowest Common Ancestor Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.37 kb
#include <fstream>
#include <vector>
using namespace std;

#define MAX 100001
#define MAXLOG2 18

vector<int> graf[MAX];
int n, m;

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

int nivel[MAX];
int euler[2 * MAX];
int eloca[MAX];
int neuler;
int rmat[2 * MAX][MAXLOG2];
int log[2 * MAX];
int putere[2 * MAX];
void dfs(int x, int parinte){
  euler[++neuler] = x;
  nivel[neuler] = nivel[parinte] + 1;
  eloca[x] = neuler;

  for (vector<int>::iterator i = graf[x].begin(); i != graf[x].end(); i++) {
    dfs(*i, neuler);
    euler[++neuler] = x;
    nivel[neuler] = nivel[parinte] + 1;
  }
}

void rmq() {
  int cata = 0,put = 1;
  for (int i = 1; i <= neuler; i++){
    while (put * 2 <= i) put *= 2;
    putere[i] = cata;
    rmat[i][0] = i;

  }
  for (int i = 1; i <= neuler; i++) {
    for (int j = 1; (1<<j) <= i; j++) {
      int a = rmat[i - (1<<(j - 1))][j - 1];
      int b = rmat[i][j - 1];
      if (nivel[a] > nivel[b])
        rmat[i][j] = b;
      else
        rmat[i][j] = a;
    }
  }
  for (int j = 1; j <= 7; j++) {
    for (int i = 1; i <= neuler; i++) {
      printf("%d ",rmat[i][j]);
    }
    printf("\n");
  }
}
int lca(int a, int b) {
  a = nivel[a];
  b = nivel[b];
  if (a > b) {
    int aux = a;
    a = b;
    b = aux;
  }
  int p = putere[b - a + 1];
  int x = rmat[a + (1<<p) - 1][p];
  int y = rmat[b][p];

  if (nivel[x] > nivel[y])
    return euler[y];
  return euler[x];
}
int main() {
  in>>n>>m;

  for (int i = 2; i <= n; i++) {
    int x;
    in>>x;
    graf[x].push_back(i);
  }
  nivel[0] = -1;
  dfs(1,0);
  rmq();
  for (int i = 1; i <= m; i++){
    int a, b;
    in>>a>>b;
    out<<lca(a, b)<<"\n";
  }

  return 0;
}
/*

int K, N, M;
int L[MAX_N << 1], H[MAX_N << 1],Lg[MAX_N << 1], First[MAX_N];
int Rmq[MAX_L][MAX_N << 2];

vector <int> G[MAX_N];

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

void citire()
{
    fin >> N >> M;

    for(int i = 2; i <= N; ++i)
    {
        int x;
        fin >> x;
        G[x].push_back(i);
    }
}

void dfs(int nod, int lev)
{
    H[++K] = nod; //nodul actual este adaugat in reprezentarea Euler a arborelui
    L[K] = lev; //se retine nivelul fiecarei pozitii din reprezentarea Euler a arborelui
    First[nod] = K; //se retine si prima aparitie a fiecarui nod in reprezentarea Euler a arborelui

    foreach(G[nod])
    {
        dfs(*it, lev+1);

        H[++K] = nod;
        L[K] = lev;
    }
}

void rmq()
{
//in Rmq[i][j] va fi nodul de nivel minim dintre pozitiile (j, j + 2^i - 1) din reprezentarea Euler a arborelui
    for(int i = 2; i <= K; ++i)
        Lg[i] = Lg[i >> 1] + 1;
    for(int i = 1; i <= K; ++i)
        Rmq[0][i] = i;

    for(int i = 1; (1 << i) < K; ++i)
        for(int j = 1; j <= K - (1 << i); ++j)
        {
            int l = 1 << (i - 1);

            Rmq[i][j] = Rmq[i-1][j];
            if(L[Rmq[i-1][j + l]] < L[Rmq[i][j]])
                Rmq[i][j] = Rmq[i-1][j + l];
        }
  for (int i = 0; i <= 8; i++) {
    for (int j = 1; j <= K; j++)
      printf("%3d", Rmq[i][j]);
    printf("\n");
  }
}

int lca(int x, int y)
{
//LCA-ul nodurilor x si y va fi nodul cu nivel minim din secventa (First[x], First[y]) din reprezentarea Euler a arborelui
    int diff, l, sol, sh;
    int a = First[x], b = First[y];
    if(a > b) swap(a, b);
    diff = b - a + 1;
    l = Lg[diff];
    sol = Rmq[l][a];
    sh = diff - (1 << l);
    if(L[sol] > L[Rmq[l][a + sh]])
        sol = Rmq[l][a + sh];
    return H[sol];
}
*/