Cod sursa(job #717978)

Utilizator PetcuIoanPetcu Ioan Vlad PetcuIoan Data 20 martie 2012 13:00:23
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.54 kb
#include<stdio.h>
#include<assert.h>

#include<algorithm>
#include<vector>

using namespace std;

const int knmax = 220005;
int numbers, qrys, size, vis[knmax / 2], last_seen[knmax / 2], pows[knmax], rmq[20][knmax];
vector<int> graph[knmax / 2];

void read(){
  assert(freopen("lca.in", "r", stdin) != NULL);

  scanf("%d%d", &numbers, &qrys);

  int aux;
  for(int i = 2; i <= numbers; ++i){
    scanf("%d", &aux);
    graph[aux].push_back(i);
  }

}

void dfs(int x){
  vis[x] = 1;
  rmq[0][++size] = x;

  for(vector<int>::iterator it = graph[x].begin(); it < graph[x].end(); ++it)
    if(!vis[*it]){
      dfs(*it);
      rmq[0][++size] = x;
  }

}

void solve(){
  dfs(1);

  for(int i = 1; i <= size; ++i)
    last_seen[rmq[0][i]] = i;

  int i, j;
  for(j = 1; j <= 18; ++j)
    for(i = 1; i <= size; ++i)
      if(i + (1 << (j - 1)) > size)
        rmq[j][i] = rmq[j - 1][i];
      else
        rmq[j][i] = min(rmq[j - 1][i], rmq[j - 1][i + (1 << (j - 1))]);

  for(i = 1, j = 0; i <= size; ++i){
    if(i == 1 << (j + 1))
      ++j;
    pows[i] = j;
  }

}

inline int query(int left, int right){
  int len = right - left + 1;
  return min(rmq[pows[len]][left], rmq[pows[len]][right - (1 << pows[len]) + 1]);
}

void write(){
  assert(freopen("lca.out", "w", stdout) != NULL);

  int aux_x, aux_y;
  for(int i = 1; i <= qrys; ++i){
    scanf("%d%d", &aux_x, &aux_y);
    if(last_seen[aux_x] > last_seen[aux_y])
      swap(aux_x, aux_y);
    printf("%d\n", query(last_seen[aux_x], last_seen[aux_y]));
  }

}

int main(){
  read();
  solve();
  write();
  return 0;
}