Cod sursa(job #3361463)

Utilizator EricDimiCismaru Eric-Dimitrie EricDimi Data 24 iulie 2026 15:22:20
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.43 kb
#include <fstream>
#include <vector>

using namespace std;

ifstream f("lca.in");
ofstream g("lca.out");

const int MAX_N = 100000,
          MAX_LOG2 = 18,
          INF = 1000000000;

struct SparseTable
{
    int st[MAX_LOG2 + 1][MAX_N << 1];
    int log2[MAX_N << 1];
    int *arr;
    int n;

    int Combine(int x, int y)
    {
        return (arr[x] < arr[y]) ? x : y;
    }

    void Init(int *arr, int n)
    {
        this->arr = arr;
        this->arr[0] = INF;
        this->n = n;
    }

    void Preprocess()
    {
        log2[1] = 0;
        for(int i = 2; i <= n; i++)
            log2[i] = log2[i >> 1] + 1;
        for(int i = 1; i <= n; i++)
            st[0][i] = i;
        for(int p = 1; p <= log2[n]; p++)
            for(int i = 1; i + (1 << p) - 1 <= n; i++)
                st[p][i] = Combine(st[p - 1][i], st[p - 1][i + (1 << (p - 1))]);
    }

    int Query(int left, int right)
    {
        int len = log2[right - left + 1];
        return Combine(st[len][left], st[len][right - (1 << len) + 1]);
    }
};

struct Tree
{
    vector<int> adj[MAX_N + 1];
    int euler[MAX_N << 1],
        depth[MAX_N << 1],
        pos[MAX_N + 1];
    int n, q, timer;

    SparseTable sparseTable;

    void Read()
    {
        f >> n >> q;
        for(int y = 2; y <= n; y++)
        {
            int x;
            f >> x;
            adj[x].push_back(y);
        }
    }

    void DFS(int node, int dist = 0)
    {
        ++timer;
        euler[timer] = node;
        depth[timer] = dist;
        pos[node] = timer;
        for(int child : adj[node])
        {
            DFS(child, dist + 1);
            ++timer;
            euler[timer] = node;
            depth[timer] = dist;
        }
    }

    void InitSparseTable()
    {
        timer = 0;
        DFS(1);
        sparseTable.Init(depth, timer);
        sparseTable.Preprocess();
    }

    int LCA(int x, int y)
    {
        int left = pos[x],
            right = pos[y];
        if(left > right)
            swap(left, right);
        return euler[sparseTable.Query(left, right)];
    }

    void Solve()
    {
        while(q--)
        {
            int x, y;
            f >> x >> y;
            g << LCA(x, y) << '\n';
        }
    }
};
Tree tree;

int main()
{
    tree.Read();
    tree.InitSparseTable();
    tree.Solve();

    f.close();
    g.close();

    return 0;
}