Cod sursa(job #533042)

Utilizator icepowdahTudor Didilescu icepowdah Data 12 februarie 2011 22:03:39
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.33 kb
#include <fstream>
#include <vector>
using namespace std;

#define NMAX 100005
#define LOGMAX 21

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

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

void preprocess() {
  int i,j;
  for (i=1;i<=I;i++) mins[0][i] = i;
  for (j=1;(1<<j)<I;j++) {
    int k = 1<<(j-1);
    for (i=1;i+(1<<j)-1<=I;i++) {      
      mins[j][i] = mins[j-1][i];
      if (depths[mins[j-1][i+k]]<depths[mins[j][i]])
        mins[j][i] = mins[j-1][i+k];
    }
  }
}

int main() {
  int i,j,x,k,dif,a,b, min;
  f>>N>>M;
  for (i=2;i<=N;i++) {
    f>>x;
    tree[x].push_back(i);
  }
  euler_traversal(1,0);
  preprocess();
  for (x=1;x<=M;x++) {
    f>>a>>b;
    i = seen_first[a]; j = seen_first[b];
    if (i>j) swap(i,j);
    dif = j-i+1, k=0;
    for (k=0;dif;dif>>=1,k++); k--;
    min = mins[k][j-(1<<k)+1];
    if (depths[min] > depths[mins[k][i]]) 
      min = mins[k][i];
    g<<euler[min]<<"\n";
  }
  f.close(); g.close(); return 0;
}