Cod sursa(job #2839010)

Utilizator BalasaRaduBalasa Radu BalasaRadu Data 25 ianuarie 2022 08:49:27
Problema Lowest Common Ancestor Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.76 kb
#include <bits/stdc++.h>
using namespace std;

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

const int dim=100009;

vector<int>v[dim];

int len,nivel[dim];
int euler[2*dim],aparitie[dim];

void DFS(int x,int tata){
    euler[++len]=x;
    nivel[x]=nivel[tata]+1;
    aparitie[x]=len;
    for(int y:v[x]){
        DFS(y,x);
        euler[++len]=x;
    }
}

struct SegmentTree{
    int aint[4*dim];
    void update(int nod,int tl,int tr,int poz,int val){
        if(tl==tr){
            aint[nod]=val;
            return;
        }
        int tm=(tl+tr)/2;
        if(poz<=tm){
            update(2*nod,tl,tm,poz,val);
        }
        else{
            update(2*nod+1,tm+1,tr,poz,val);
        }
        aint[nod]=(nivel[aint[2*nod]]<nivel[aint[2*nod+1]]) ? aint[2*nod]:aint[2*nod+1];
    }
    int query(int nod,int tl,int tr,int l,int r){
        if(l==tl && r==tr){
            return aint[nod];
        }
        int tm=(tl+tr)/2;
        if(r<=tm){
            return query(2*nod,tl,tm,l,r);
        }
        if(l>tm){
            return query(2*nod+1,tm+1,tr,l,r);
        }
        int n1=query(2*nod,tl,tm,l,tm);
        int n2=query(2*nod+1,tm+1,tr,tm+1,r);
        return (nivel[n1]<nivel[n2]) ? n1 : n2;
    }
}B;

void find_lca(){
    DFS(1,0);
    for(int i=1;i<=len;i++){
        B.update(1,1,len,i,euler[i]);
    }
}

int lca(int a,int b){
    a=aparitie[a];
    b=aparitie[b];
    if(a>b){
        swap(a,b);
    }
    return B.query(1,1,len,a,b);
}

signed main(){
    int n,q;
        fin>>n>>q;
    for(int i=2;i<=n;i++){
        int j;
        fin>>j;
        v[j].push_back(i);
    }
    find_lca();
    while(q--){
        int l,r;
        fin>>l>>r;
        fout<<lca(l,r)<<'\n';
    }
}