Cod sursa(job #2799153)

Utilizator mircea_007Mircea Rebengiuc mircea_007 Data 12 noiembrie 2021 15:51:59
Problema Lowest Common Ancestor Scor 20
Compilator c-64 Status done
Runda Arhiva educationala Marime 2.3 kb
#include <stdio.h>
#include <ctype.h>

// Program de Mircea Rebengiuc
// inceput pe 2021.11.12

#define MAXB (128 * 1024)
#define MAXN 100000
#define MAXEULER (2 * MAXN)
#define MAXM 2000000
#define NIL -1
#define MAXL 18

int depth[MAXN];
int first[MAXN];
int kids[MAXN];
int adj[MAXM];
int next[MAXN];

int euler[MAXEULER];
int sp;

int rmq[MAXL][MAXEULER];
int logcalc[MAXEULER + 1];

// euler tour
void getEuler( int root, int parrent ){
  int i = kids[root];

  first[root] = sp;
  euler[sp++] = root;

  while( i != NIL ){
    depth[adj[i]] = 1 + depth[root];
    getEuler(adj[i], root);
    euler[sp++] = root;

    i = next[i];
  }
}

// rmq

void rmqInit( int n ){
  int l = 1, p2 = 2, i;

  for( i = 0 ; i < n ; i++ )
    rmq[0][i] = euler[i];

  for( p2 = 2 ; p2 <= n ; p2 *= 2 ){
    for( i = 0 ; i < n + 1 - p2 ; i++ )
      rmq[l][i] = depth[rmq[l - 1][i]] < depth[rmq[l - 1][i + (p2 >> 1)]] ? rmq[l - 1][i] : rmq[l - 1][i + (p2 >> 1)];
    l++;
  }

  logcalc[1] = 0;
  for( i = 2 ; i <= n ; i++ )
    logcalc[i] = 1 + logcalc[i >> 1];
}

static inline void order2( int *a, int *b ){
  int aux;
  
  if( (*a) > (*b) ){
    aux = *a;
    *a = *b;
    *b = aux;
  }
}

int rmqQuery( int a, int b ){
  order2(&a, &b);
  int l = logcalc[b - a + 1], p2 = (1 << logcalc[b - a + 1]);
  
  return depth[rmq[l][a]] < depth[rmq[l][b - l + 1]] ? rmq[l][a] : rmq[l][b - p2 + 1];
}

// fast i/o
FILE *fin, *fout;

char ibuf[MAXB];
int ibp = MAXB - 1;

static inline int bgetc(){
  if( (ibp = ((ibp + 1) & (MAXB - 1))) == 0 )
    fread(ibuf, sizeof(char), MAXB, fin);
  return ibuf[ibp];
}

static inline int fgetint(){
  int n = 0, ch;

  while( !isdigit(ch = bgetc()) );
  do
    n = n * 10 + ch - '0';
  while( isdigit(ch = bgetc()) );

  return n;
}

int main(){
  fin  = fopen("lca.in",  "r");
  fout = fopen("lca.out", "w");

  int n, m, i, a, b;

  n = fgetint();
  for( i = 0 ; i < n ; i++ )
    kids[i] = NIL;
  
  m = fgetint();
  
  for( i = 0 ; i < n - 1 ; i++ ){
    a = fgetint() - 1;

    adj[i] = i + 1;
    next[i] = kids[a];
    kids[a] = i;
  }

  // parcurgerea euler
  sp = 0;
  depth[0] = 0;
  getEuler(0, 0);

  rmqInit(sp);

  for( ; m-- ; ){
    a = fgetint() - 1;
    b = fgetint() - 1;

    fprintf(fout, "%d\n", 1 + rmqQuery(first[a], first[b]));// n-am chef si de parsare de out
  }

  fclose(fin);
  fclose(fout);
  return 0;
}