Cod sursa(job #3263407)

Utilizator axetyNistor Iulian axety Data 14 decembrie 2024 11:15:48
Problema Lowest Common Ancestor Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.94 kb
#include <fstream>
#include <cmath>
#include <stdlib.h>
#include <algorithm>
#include <vector>
#include <utility>
using namespace std;

ifstream fin ("lca.in");
ofstream fout ("lca.out");

/**
 * 
 * RMQ (range minimum query) ; 
 *       |      |       |
 *      i j   numerele  !
 *          pot sa apara
 *       de mai multe ori
 * 
 *    10 elem.
 * 
 *    1 5 8 3 9 14 17 7 20 9 
 *      
 * 
 *  rmq[n][log n] 
 * 
 * i=1,n
 * j=1,logn
 * 1<<j
 * 
 * rmq[i][0]=v[i]
 * rmq[i][j]=min(rmq[i][j-1],rmq[i+2^j])
 * 
 * rmq[i][j]=rez pe interval de la i de lungime 2^j
 * 
 * [x,y] = rmq[x][l]
 *         rmq[y-l+1][l]
 * 
 * p2[i]-> 2^j<=i, 2^j maxim
 * 
 * p2[i-1] sau p2[i-1]*2
 * 
 *  Lowest common ancestor ( LCA ) :
 * 
 *  x , y 
 * 
 *      
 * 
**/

int n,m,x,y,dif,l;
int kN;
pair<int,int>rmq[200001][20];
int p2[100001];
vector<int>matAdj[100001];
pair<int,int> euler[200001];
int pozitii[100001];

void dfs(int nod,int k){

    pozitii[nod]=++kN;
    euler[kN] = {k,nod};
    for(auto i : matAdj[nod])
    {
        dfs(i,k+1);
        euler[++kN]= {k,nod};
    }
    
}


void create()   
{
   

   p2[1]=0;
   for(int i=2;i<=2*n;i++)
   {
    p2[i]=p2[i-1];
    if((1<<(p2[i]+1)) <=i)
        p2[i]++;
   }

   dfs(1,0);

   n=kN;

   for(int i=1;i<=n;i++)
   {
    rmq[i][0]=euler[i];
   } 

   for(int j=1;(1<<j)<=n;j++)
   {
      for(int i=1;i<=n-(1<<j)+1;i++)
      {
        rmq[i][j]=min(rmq[i][j-1],rmq[i+(1<<(j-1))][j-1]);
      }
   }
}

int main(){
    fin >> n >> m;
    for(int i=1;i<n;i++)
    {
        fin >>x;
        matAdj[x].push_back(i+1);
    }
    create();
    for(int q=1;q<=m;q++)
    {            
       fin >> x >> y;
       int xX=min(pozitii[x],pozitii[y]);
       int yY=max(pozitii[x],pozitii[y]);
       l=yY-xX+1;
       fout << min(rmq[xX][p2[l]], rmq[yY-(1<<p2[l])+1][p2[l]]).second << '\n';
    }
    return 0;
}