Cod sursa(job #531774)

Utilizator Gaby_mMititelu Gabriel Gaby_m Data 10 februarie 2011 11:52:11
Problema Lowest Common Ancestor Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 1.62 kb
#include <fstream>
#include <vector>
using namespace std;

#define NMAX 100001

int N, M, I;
ifstream f("lca.in"); ofstream g("lca.out");
int euler[NMAX<<1], depths[NMAX<<1], seen_first[NMAX], int_tree[NMAX<<2];
vector<int> tree[NMAX];

void euler_tour(int node, int level) {
  euler[++I] = node, depths[I] = level, seen_first[node] = I;
  for (vector<int>::iterator it=tree[node].begin();it!=tree[node].end();it++) {
    euler_tour(*it, level+1);
    euler[++I] = node, depths[I] = level;
  }
}

void update_int_tree(int nod, int st, int dr) {
  if (st == dr) {
    int_tree[nod] = st;
  }
  else {
    int mid = (st+dr)>>1, left=nod<<1, right=left|1;
    update_int_tree(left,st,mid);
    update_int_tree(right,mid+1,dr);
    if (depths[int_tree[left]]<=depths[int_tree[right]]) {
      int_tree[nod] = int_tree[left];
    }
    else int_tree[nod] = int_tree[right];
  }
}

int lookup(int nod, int st, int dr, int a, int b) {
  if (a<=st && dr<=b) {
    return int_tree[nod];
  }
  else {
    int min=INT_MAX;
    int mid = (st+dr)>>1, left=nod<<1, right=left|1;
    if (a<=mid) {
      min = lookup(left,st,mid,a,b);
    }
    if (mid<b) {
      int x = lookup(right,mid+1,dr,a,b);
      if (depths[x] < depths[min]) {
        min = x;
      }
    }
    return min;
  }
}

int lca(int x, int y) {
  int a = seen_first[x], b=seen_first[y];
  if (a>b) swap(a,b);
  return euler[lookup(1,1,I,a,b)];
}

int main() {
  int x,y;
  f>>N>>M;  
  for (int i=2;i<=N;i++) {
    f>>x;
    tree[x].push_back(i);
  }
  euler_tour(1,0);
  update_int_tree(1,1,I);
  for (int i=1;i<=M;i++) {
    f>>x>>y;
    g<<lca(x,y)<<"\n";
  }
  f.close(); g.close();
  return 0;
}