Cod sursa(job #2821757)

Utilizator Remus.RughinisRemus Rughinis Remus.Rughinis Data 22 decembrie 2021 23:44:17
Problema Lowest Common Ancestor Scor 0
Compilator c-64 Status done
Runda Arhiva educationala Marime 2.46 kb
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MAXN 100000
#define EULER 10000000 ///? (Am dat la intamplare)

int p[MAXN],min[MAXN],e[EULER],nv[EULER],bt[318][2];

int nr,n;

static inline int f(int a, int b){
  if(a>b)
    return a;
  return b;
}

int query(int a, int b){
  int poz,f,rad = sqrt(n),st,dr;


  st = (a + rad - 1) / rad * rad;
  dr = b / rad * rad;

  f = nv[a];
  poz = a;
  a++;
  while (a <= b && a < st){
    if(nv[a] < f){
      f = nv[a];
      poz = a;
    }

    a++;
  }
  while (b >= a && b >= dr){
    if(nv[b] < f){
      f = nv[b];
      poz = b;
    }

    b--;
  }

  st /= rad;
  dr /= rad;

  while (st < dr){
    if(bt[st][0] < f){
      f = bt[st][0];
      poz = bt[st][1];
    }

    st++;
  }

  return poz;
}

void euler(int x, int lvl){
  int i;

  e[nr] = x;
  nv[nr] = lvl;
  nr++;

  i = min[x];
  while(i < n && p[i] == x){
    euler(i,lvl+1);
    i++;
  }

  if(x != 0){
    e[nr] = p[x];
    nv[nr] = lvl-1;
    nr++;
  }
}

int main(){
  int i,m,a,b,rad,ai,bi,j;
  FILE *fin, *fout;

  fin = fopen("lan.in","r");
  fscanf(fin,"%d%d",&n,&m);

  p[0] = 0;
  for(i=1;i<n;i++){ ///Construim Euler
    fscanf(fin,"%d",&p[i]);
    p[i] --;

    if(min[p[i]] == 0)
      min[p[i]] = i; ///Marcam care este primul copil care il are pe i parinte
  }

  nr = 0;
  euler(0,0);

  fout = fopen("lan.out","w");

  n = nr;
  rad = sqrt(n);
  for(i=0;i<=rad+1;i++){
    bt[i][1] = -1;
  }
  for(i=0;i<n;i++){ /// Precalculare Batog
    ///b[i] = i*rad + (i*rad + 1) + (i*rad + 2) + ... + (i+1)* rad-1
    if(nv[i] < bt[i/rad][0] || bt[i/rad][1] == -1){
      bt[i/rad][0] = nv[i];
      bt[i/rad][1] = i;
    }
  }

//  for(i=0; i<=rad+1; i++)
//    printf("%d ",bt[i][0]);
//  printf("\n\n");

//  int st1=8;
//  int dr1=19;
//  printf("%d - %d: %d\n",st1,dr1,query(st1,dr1));


//  for(i=0; i<nr; i++)
//    printf("%d ",e[i] + 1);
//  printf("\n");
//  for(i=0; i<nr; i++)
//    printf("%d ",nv[i]);
//  printf("\n");


  for(i = 0; i < m; i ++){
    fscanf(fin,"%d%d",&a,&b);
    ai = 0;
    bi = 0;
    for(j=0;j<n;j++){
      if(ai == 0 && e[j] == a-1)
        ai = j;
      if(bi == 0 && ai!=0 && e[j] == b-1)
        bi = j;
    }

    fprintf(fout,"%d\n",e[query(ai,bi)] + 1); ///Acum face intre pozitiile a si b in euler, nu intre pozitiile elementelor a si b
  }
  fclose(fin);

  fclose(fout);
  return 0;
}