Cod sursa(job #3305363)

Utilizator jumaracosminJumara Cosmin-Mihai jumaracosmin Data 1 august 2025 02:30:53
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.32 kb
#include <bits/stdc++.h>
    
std::ifstream fin("lca.in");
std::ofstream fout("lca.out");

//#define fin std::cin
//#define fout std::cout

/*
    LCA - Tarjan's offline LCA 
    --------------
    -> Fac un DFS in care ma folosesc de DSU pentru a gasi raspunsuri pe subarbori
    -> Algoritmul este offline, deci trebuie sa stiu toate query-urile memorate inainte de rulare

*/

const int nmax = 1e5 + 5;
const int qmax = 2e6 + 5;

int n, q;
std::vector<int> graph[nmax];

int father[nmax];     // pentru DSU
int ancestor[nmax];   // ancestor[i] = care este cel mai de sus stramos al componentei lui x
int visited[nmax];

std::vector<std::pair<int, int>> queries[nmax]; // query[x] = {(v, idx) | exista query (x, y) fiind al idx-lea query}
int query_answer[qmax];

int Find(int x)
{
    if(father[x] != x)
        father[x] = Find(father[x]);
    return father[x];
}

void Union(int x, int y)
{
    int father_x = Find(x);
    int father_y = Find(y);
    father[father_y] = father_x;
}

void dfs(int node)
{
    father[node] = node;
    ancestor[node] = node;
    visited[node] = true;

    for(int adj : graph[node])
        if(!visited[adj])
        {
            dfs(adj);                       // merg recursiv in subarbore
            Union(node, adj);               // unesc surbarborele lui adj la node
            //ancestor[Find(node)] = node;    // LCA(x, y), unde x si y sub din subarborele cu radacina node
        }

    for(auto pair : queries[node])          // pot raspunde la queries (x, node) daca am vizitat si nodul x
    {
        int adj = pair.first;
        int idx = pair.second;

        if(visited[adj])                    // ancestor[Find(adj)] este LCA-ul, radacina subtree-ului cel mai adanc
            query_answer[idx] = ancestor[Find(adj)];  // ce contine ambele noduri
    }
}


int main()
{
    
    fin >> n >> q;
    for(int i = 2; i <= n; ++i)
    {
        int x;
        fin >> x;
        graph[i].push_back(x);
        graph[x].push_back(i);
    }

    for(int i = 1; i <= q; ++i)
    {
        int x, y;
        fin >> x >> y;
        queries[x].push_back({y, i});
        queries[y].push_back({x, i});
    }

    int root = 1;
    dfs(root);

    for(int i = 1; i <= q; ++i)
        fout << query_answer[i] << "\n";

    return 0;
}