Cod sursa(job #373739)

Utilizator perticas_catalinperticas catalin perticas_catalin Data 14 decembrie 2009 22:23:47
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.64 kb
#include<iostream>
#include<string>
#include<vector>

using namespace std;

#define NM 200005
#define PM 18
#define PB push_back
#define FOR(i,a,b) for(i=(a);i<=(b);++i)
#define maxbuf 65536

FILE*fin=fopen("lca.in","r");

int N,M,dim,LEVEL[NM],CARE[NM],RMQ[NM][PM],ind,FA[NM],L[NM];

vector<int> G[NM];

char buf[maxbuf];

inline void refbuf()
{
     int ans=fread(buf,1,maxbuf,fin);
     
     if(ans<maxbuf) buf[ans]=0;
     
     ind=0;  
}

inline int readnr()
{
     int ans=0;
     
     one:
         while(ind<maxbuf && !isdigit(buf[ind])) ++ind;
         if(ind==maxbuf)
         {
           refbuf();
           goto one;
         }  
         
     two:
         while(ind<maxbuf && isdigit(buf[ind]))
         {
           ans=ans*10+buf[ind]-'0';
           ++ind;
         }    
         if(ind==maxbuf)
         {
           refbuf();
           goto two;
         }
     return ans;    
}

void euler(int nod,int lev)
{
     int i,sz=G[nod].size();
     
     LEVEL[nod]=lev;
     CARE[++dim]=nod;
     
     FA[nod]=dim;
     
     for(i=0;i<sz;++i)
     {
       int nnod=G[nod][i];
       
       euler(nnod,lev+1);
       
       CARE[++dim]=nod;
     }
     
}

int main()
{
    int nod,i,l;
    
    refbuf();
    
    //freopen("lca.in","r",stdin);
    freopen("lca.out","w",stdout);
    
    N=readnr();
    M=readnr();
    
    FOR(i,2,N)
    {
      nod=readnr();
      
      G[nod].PB(i);
    }
    
    euler(1,0);
    /*
    FOR(i,1,dim)
      printf("%d ",CARE[i]);
      
    printf("\n");  
    
     FOR(i,1,dim)
      printf("%d ",LEVEL[CARE[i]]);
    */
    
    int cat=0,poz=1;
    
    while(poz<dim)
    {
      int end=poz+(1<<cat)-1;
      
      while(poz<=dim && poz<=end)
      {
        L[poz]=cat;
        ++poz;
      }
      
      ++cat;
    }
    
    FOR(i,1,dim)
      RMQ[i][0]=CARE[i];
    
    FOR(l,1,17)
      FOR(i,1,dim)
      {
        if(i+(1<<l)-1>dim) break;
        
        //RMQ[i][l]=min(RMQ[i][l-1],RMQ[i+(1<<(l-1))][l-1]);
        
        if(LEVEL[RMQ[i][l-1]]<LEVEL[RMQ[i+(1<<(l-1))][l-1]])
          RMQ[i][l]=RMQ[i][l-1];
        else
          RMQ[i][l]=RMQ[i+(1<<(l-1))][l-1];
      }  
    
    FOR(i,1,M)
    {
      int n1=readnr();
      int n2=readnr();
      
      int a=FA[n1],b=FA[n2];
      
      if(b<a)
      {
        int aux=a;
        a=b;
        b=aux;
      }
      
      l=L[b-a+1];
      
      if(LEVEL[RMQ[a][l]]<LEVEL[RMQ[b-(1<<l)+1][l]]) printf("%d\n",RMQ[a][l]);
      else printf("%d\n",RMQ[b-(1<<l)+1][l]);
    }
    
    return 0;
}