Cod sursa(job #2698746)

Utilizator CiubarLoverBaiatu cu Ciubaru CiubarLover Data 22 ianuarie 2021 21:50:06
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.47 kb
#include <bits/stdc++.h>

using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");
int n,m;
int tata;
int first_nod[100005];/// first_nod[i]=prima aparitie a lui i in vectorul lin
int last_nod[100005];/// last_nod[i]=ultima aparitie a lui i in vectorul lin
int rmq[18][200005];/// =nodul cu cea mai mica adancime
vector<int>lin,val;/// reprezentarea liniara a arborelui + adancimile corespunzatoare
vector<int>nod[100005];
void go_visit(int pos,int depth)
{
    ///Marcam prima si ultima aparitie a nodului in forma liniara a arborelui
    first_nod[pos]=last_nod[pos]=lin.size();

    ///Marcam intrarea in nodul 'pos'
    lin.push_back(pos);
    val.push_back(depth);

    for(auto fiu: nod[pos])
    {
        ///Parcurgem fiecare fiu pentru a aduga arborele acestuia in reprezentarea liniara
        go_visit(fiu,depth+1);
        ///Marcam faptul ca ne intoarcem in nodul 'pos'
        last_nod[pos]=lin.size();
        lin.push_back(pos);
        val.push_back(depth);
    }
}
void create_rmq()
{
    /// Ne cream rmq-ul ce ne ajuta sa gasim lca-ul prin gasirea celei mai mici adancimi
    for(int i=0;i<2*n-1;i++)
        rmq[0][i]=i;

    for(int pw=1;(1<<pw)<=2*n-1;pw++)
        for(int i=0;i+(1<<pw)<2*n;i++)
            if(val[rmq[pw-1][i]]>val[rmq[pw-1][i+(1<<(pw-1))]])
                rmq[pw][i]=rmq[pw-1][i+(1<<(pw-1))];
            else
                rmq[pw][i]=rmq[pw-1][i];
}
int take_ans(int x,int y)
{
    /// Prima data, verificam daca x/y e stramos a lui y/x
    if(first_nod[x]>first_nod[y])
        swap(x,y);
    if(last_nod[x]>=last_nod[y])
        return x;

    /// Trebuie sa gasim cea mai mica adancime in intervalul i->j (adancimea lca-ului)
    int j=first_nod[y];
    int i=last_nod[x];
    int diff=j-i+1;

    int pw=17;
    while((1<<pw)>diff)
        pw--;

    /// Returnarea raspunsului
    if(val[rmq[pw][i]]>val[rmq[pw][j-(1<<pw)+1]])
        return lin[rmq[pw][j-(1<<pw)+1]];
    return lin[rmq[pw][i]];
}
int main()
{
    fin>>n>>m;
    for(int fiu=2;fiu<=n;fiu++)
    {
        fin>>tata;
        nod[tata].push_back(fiu);///adaugam muchia de la tata la fiu
    }

    ///     Liniarizarea arborelui
    go_visit(1,0);///parcurgem tot arborele incepand cu radacina
    create_rmq();

    ///     Citirea intrebarilor si formarea raspunsului pentru fiecare intrebare
    int x,y;
    while(m--)
    {
        fin>>x>>y;
        fout<<take_ans(x,y)<<"\n";
    }
    return 0;
}