Cod sursa(job #929955)

Utilizator PetcuIoanPetcu Ioan Vlad PetcuIoan Data 27 martie 2013 12:56:21
Problema Lowest Common Ancestor Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 2.7 kb
#include<cstdio>
#include<cassert>
#include<cstring>

#include<vector>
#include<algorithm>
#include<fstream>
#include<iostream>
#include<queue>

using namespace std;

const int kinf = 2e9;

class node{
public:

  node(){};

  node(int left1, int right1, int ltree1, int rtree1, int val1){
    left = left1;
    right = right1;
    ltree = ltree1;
    rtree = rtree1;
    val = val1;
  }

  friend void make(int nod);
  friend void update(int pos, int val, int nod);
  friend int query(int l, int r, int nod);

private:
  int left, right, ltree, rtree, val;
};

vector<node> t;
int p, init[300005];

void make(int nod){
  if(t[nod].left != t[nod].right){
    p = t.size();
    t[nod].ltree = p;
    t.push_back(node(t[nod].left, (t[nod].left + t[nod].right) >> 1, 0, 0, 0));
    ++p;
    t[nod].rtree = p;
    t.push_back(node(((t[nod].left + t[nod].right) >> 1) + 1, t[nod].right, 0, 0, 0));
    make(t[nod].ltree);
    make(t[nod].rtree);
    t[nod].val = min(t[t[nod].ltree].val, t[t[nod].rtree].val);
  }
  else
    t[nod].val = init[t[nod].left];
}

void update(int pos, int val, int nod){
  if(t[nod].left == t[nod].right){
    t[nod].val = val;
    return;
  }

  if(pos <= (t[nod].left + t[nod].right) >> 1)
    update(pos, val, t[nod].ltree);
  else
    update(pos, val, t[nod].rtree);

  t[nod].val = min(t[t[nod].ltree].val, t[t[nod].rtree].val);
}

int query(int l, int r, int nod){
  if(l <= t[nod].left && r >= t[nod].right)
    return t[nod].val;
  if(l > t[nod].right || r < t[nod].left)
    return kinf;

  return min(query(l, r, t[nod].ltree), query(l, r, t[nod].rtree));
}

int u, vis[100005], ind[100005], num[100005], pos[100005];
vector<int> graph[100005];

void bfs(){
  memset(vis, 0, sizeof(vis));
  int n = 0;
  queue<int> q;
  q.push(1);
  vis[1] = 1;
  ind[1] = ++n;
  num[n] = 1;
  while(!q.empty()){
    int now = q.front();
    q.pop();

    for(int i = 0; i < graph[now].size(); ++i)
      if(!vis[graph[now][i]]){
        vis[graph[now][i]] = 1;
        ind[graph[now][i]] = ++n;
        num[n] = graph[now][i];
        q.push(graph[now][i]);
      }

  }

}

void dfs(int x){
  vis[x] = 1;
  init[++u] = x;
  pos[x] = u;
  for(int i = 0; i < graph[x].size(); ++i)
    if(!vis[graph[x][i]]){
      dfs(graph[x][i]);
      init[++u] = x;
    }
}

int main(){
  ifstream in("lca.in");
  ofstream out("lca.out");

  int n, x, y, m;
  in >> n >> m;
  for(int i = 2; i <= n; ++i){
    in >> x;
    graph[x].push_back(i);
    graph[i].push_back(x);
  }

  dfs(1);
  bfs();

  for(int i = 1; i <= u; ++i)
    init[i] = ind[init[i]];

  t.push_back(node(1, u, 0, 0, 0));
  make(0);

  for(int i = 0; i < m; ++i){
    in >> x >> y;
    if(pos[x] > pos[y])
      swap(x, y);
    out << num[query(pos[x], pos[y], 0)] << "\n";
  }

  return 0;
}