Cod sursa(job #2701017)

Utilizator MenelausSontea Vladimir Menelaus Data 29 ianuarie 2021 16:29:01
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.48 kb
#include <iostream>
#include <fstream>
#include <vector>

const int N=100000;
const int LOG=17;

std::ifstream in("lca.in");
std::ofstream out("lca.out");

std::vector<int> tree[N+1];

/// aici parent[i][j] va fi al 2^j-lea stramos al lui i
int parent[N+1][LOG+1];
int depth[N+1];

void preprocess(int n)
{
    //avem deja coloana 0, care reprezinta parintele direct al fiecarui punct

    for(int i=1; i<=LOG; i++)
    {
        for(int node=1; node<=n; node++)
        {
            if(parent[node][i-1]!=0)
            {
                parent[node][i]=parent[ parent[node][i-1] ][ i-1 ];
            }
        }
    }
}

int lca(int u, int v)
{
    // v va fi mai adanc ca u
    if(depth[v]<depth[u])
    {
        std::swap(u, v);
    }

    //aducem u si v la acelasi nivel
    int diferenta=depth[v]-depth[u];

    for(int i=0; i<=LOG; i++)
    {
        if((diferenta>>i)&1)
        {
            v=parent[v][i];
        }
    }

    if(u==v) return u;

    for(int i=LOG; i>=0; i--)
    {
        if(parent[u][i]!=parent[v][i])
        {
            u=parent[u][i];
            v=parent[v][i];
        }
    }

    return parent[u][0];
}

int main()
{
    int n, m, x, u, v;

    in>>n>>m;
    for(int i=2; i<=n; i++)
    {
        in>>x;

        tree[x].push_back(i);
        depth[i]=depth[x]+1;
        parent[i][0]=x;
    }

    for(int i=1; i<=m; i++)
    {
        in>>u>>v;
        out<<lca(u, v)<<"\n";
    }
}