Cod sursa(job #3361407)

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

using namespace std;

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

const int MAX_N = 100000,
          MAX_POW2 = 262144,
          INF = 1000000000;

inline void swap(int& x, int& y)
{
    x ^= y ^= x ^= y;
}

int NextPow2(int n)
{
    n |= n >> 1;
    n |= n >> 2;
    n |= n >> 4;
    n |= n >> 8;
    n |= n >> 16;
    return n + 1;
}

struct SegmentTree
{
    int tree[MAX_POW2 << 1];
    int *arr;
    int n;

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

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

        for(int i = 1; i < this->n; i++)
            tree[this->n + i - 1] = (i <= n) ? i : 0;
        for(int i = this->n - 1; i >= 1; i--)
            tree[i] = Combine(tree[i << 1], tree[i << 1 | 1]);
    }

    int Query(int left, int right)
    {
        int res = 0;
        left += this->n - 1;
        right += this->n - 1;

        while(left <= right)
        {
            if(left & 1)
                res = Combine(res, tree[left++]);
            if(!(right & 1))
                res = Combine(res, tree[right--]);

            left >>= 1;
            right >>= 1;
        }

        return res;
    }
};

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 = 0;

    SegmentTree segTree;

    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)
    {
        ++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 BuildSegTree()
    {
        DFS(1, 0);
        segTree.Build(depth, timer);
    }

    int LCA(int x, int y)
    {
        int left = pos[x],
            right = pos[y];
        if(left > right)
            swap(left, right);
        return euler[segTree.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.BuildSegTree();
    tree.Solve();

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

    return 0;
}