Cod sursa(job #2825225)

Utilizator Remus.RughinisRemus Rughinis Remus.Rughinis Data 4 ianuarie 2022 12:35:55
Problema Lowest Common Ancestor Scor 30
Compilator c-64 Status done
Runda Arhiva educationala Marime 2.36 kb
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MAXN 100000
#define EULER 10000000

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

int nr,n;

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;
  if(first[x] == 0)
    first[x] = nr;
  nv[nr] = lvl;
  nr++;

  i = min[x];
  while(i < n){
    if(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("lca.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("lca.out","w");

  n = nr;
  rad = sqrt(n);

  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] || i%rad == 0){ /// O sa fie maxim rad+1 elemente
      bt[i/rad][0] = nv[i];
      bt[i/rad][1] = i;
    }
  }

  for(i = 0; i < m; i ++){
    fscanf(fin,"%d%d",&a,&b); /// Avem de gasit nivelul minim in euler dintre pozitiile de la elementul a la elementul b
    ai = first[a-1];
    bi = first[b-1];

    if(ai < bi)
      fprintf(fout,"%d\n",e[query(ai,bi)] + 1);
    else
      fprintf(fout,"%d\n",e[query(bi,ai)] + 1);
  }
  fclose(fin);

  fclose(fout);
  return 0;
}

//  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");