Cod sursa(job #2923681)

Utilizator AndreiCroitoruAndrei Croitoru AndreiCroitoru Data 17 septembrie 2022 20:08:58
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.31 kb
/// lca cu aint, ca sa aflam minimul pe interval :)

#include <bits/stdc++.h>

using namespace std;

int const N = 100'001;

vector <int> g[N];

vector <int> height, euler, first, segtree;
vector <bool> verif;

int n;

void init()
{
    height.resize(n);
    first.resize(n);
    euler.reserve(n * 2);
    verif.assign(n, false);
}

void dfs_euler(int node, int h)
{
    verif[node] = 1;
    height[node] = h;
    first[node] = euler.size();
    euler.push_back(node);
    for(auto next: g[node])
    {
        if(!verif[next])
            dfs_euler(next, h + 1), euler.push_back(node);
    }
}

void build_segtree(int node, int start, int fin)
{
    if(start == fin)
    {
        segtree[node] = euler[start];
    }
    else
    {
        int mij = (start + fin) / 2;
        build_segtree(node * 2, start, mij);
        build_segtree(node * 2 + 1, mij + 1, fin);
        int fiu_st = segtree[node * 2], fiu_dr = segtree[node * 2 + 1];
        if(height[fiu_st] < height[fiu_dr])
            segtree[node] = fiu_st;
        else
            segtree[node] = fiu_dr;
    }
}

int query_segtree(int node, int start, int fin, int st, int dr)
{
    if(start > dr or fin < st)
        return -1;
    if(start >= st and fin <= dr)
        return segtree[node];
    int mij = (start + fin) / 2;
    int fiu_st = query_segtree(node * 2, start, mij, st, dr);
    int fiu_dr = query_segtree(node * 2 + 1, mij + 1, fin, st, dr);
    if(fiu_st == -1)
        return fiu_dr;
    if(fiu_dr == -1)
        return fiu_st;
    if(height[fiu_st] < height[fiu_dr])
        return fiu_st;
    return fiu_dr;
}

int query(int x, int y)
{
    int st = first[x];
    int dr = first[y];
    if(st > dr)
        swap(st, dr);
    return query_segtree(1, 0, euler.size() - 1, st, dr);
}


int main()
{
    ifstream cin("lca.in");
    ofstream cout("lca.out");

    int q;
    cin >> n >> q;

    init();

    for(int i = 0; i < n - 1 ; i++)
    {
        int parinte;
        cin >> parinte;
        g[parinte].push_back(i + 2);
    }

    dfs_euler(1, 0);
    int m = euler.size();
    segtree.resize(m * 4);
    build_segtree(1, 0, m - 1);


    for(int i = 0; i < q; i++)
    {
        int x, y;
        cin >> x >> y;
        cout << query(x, y) << '\n';
    }
    return 0;
}