Cod sursa(job #3313611)

Utilizator Andreea1501013Andreea Andreea1501013 Data 5 octombrie 2025 14:30:58
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.56 kb
///LCA

#include <bits/stdc++.h>

using namespace std;
int N,M,t,cnt=0,nivel=1;
vector<int> fii[1000005];
vector<pair<int,int>> euler; ///nivelul la care am ajuns prin parcurgerea DFS
unordered_map<int,int> primaAparitie;
pair<int,int> rmq[1000005][50]; ///pair de nivel cu nod
int loga[1000005];
long long expo[1000005]; ///expo[i]= cea mai mare putere de 2 mai mica ca i
int sz;

void DFS(int x)
{
    if(primaAparitie[x]==0)
    {
        primaAparitie[x]=cnt;
    }
    if(fii[x].empty()==1)
    {
        return;
    }
    for(size_t i=0;i<fii[x].size();i++)
    {
        nivel++;
        euler.push_back({nivel, fii[x][i]});
        cnt++;
        DFS(fii[x][i]);
        nivel--;
        euler.push_back({nivel,x});
        cnt++;
    }
}

void Logarithm()
{
    loga[1]=0;
    expo[1]=1;
    int l=0;
    long long p=2;
    for(int i=2;i<=sz;i++)
    {
        if(i==p)
        {
            l++;
            p*=2;
        }
        expo[i]=p/2;
        loga[i]=l;
    }
}

void RMQ()
{
    ///rmq[i][p]= minimul secventei i...i+2^p-1
    for(int i=0;i<sz;i++)
    {
        rmq[i][0]=euler[i];
    }
    long long po=1;
    for(int p=1;p<=loga[sz];p++)
    {
        for(int i=0;i<sz;i++)
        {
            if(rmq[i][p-1].first<=rmq[i+po][p-1].first)
            {
                rmq[i][p]=rmq[i][p-1];
            }
            else
            {
                rmq[i][p]=rmq[i+po][p-1];
            }
        }
        po*=2;
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    ifstream cin("lca.in");
    ofstream cout("lca.out");
    cin>>N>>M;
    for(int i=1;i<N;i++)
    {
        cin>>t;
        fii[t].push_back(i+1);

    }
    euler.push_back({1,1});
    DFS(1);
    ///caut nivelul minim intre 2 prime aparitii ==> LCA
    sz=euler.size();
    Logarithm();
    RMQ();
    int n1,n2;
    while(M--)
    {
        cin>>n1>>n2;
        int a=primaAparitie[n1], b=primaAparitie[n2];
        if(a>b)
        {
            swap(a,b);
        }
        //cout<<a<<' '<<b<<'\n';
        ///rmq de la a la b ?
        pair<int,int> p1= rmq[a][loga[b-a+1]];
        //cout<<loga[b-a+1]<<' '<<expo[b-a+1]<<' '<<b-expo[b-a+1]+1<<'\n';
        pair<int,int> p2= rmq[b-expo[b-a+1]+1][loga[b-a+1]];
        //cout<<p1.first<<' '<<p1.second<<' '<<p2.first<<' '<<p2.second<<'\n';
        if(p1.first<=p2.first)
        {
            cout<<p1.second<<'\n';
        }
        else
        {
            cout<<p2.second<<'\n';
        }

    }
    return 0;
}