Cod sursa(job #2863487)

Utilizator Casian_doispeChiriac Casian Casian_doispe Data 6 martie 2022 19:50:04
Problema Lowest Common Ancestor Scor 30
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.78 kb
#include <fstream>
#include <vector>
#include <deque>
#include <algorithm>
#include <string>

#define MOD 1999999973
#define INT_MAX 1000000000

using namespace std ;

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

int tatal[100009], e[100009], lvl[100009], primaparitie[100009] ;

vector<int> fii[100009] ;

int peuler(int nod, int poz, int level)
{
    lvl[poz] = level ;
    e[poz ++] = nod ;

    if(fii[nod].size())
    {
        for(int f = 0 ; f < fii[nod].size() ; f ++)
            poz = peuler(fii[nod][f], poz, level + 1), e[poz] = nod, lvl[poz] = level, poz ++ ;

        return poz ;
    }
    else return poz ;
}

struct nod
{
    int mid, val, st, dr ;

    nod *stfiu, *drfiu ;
};

int comp(int a, int b)
{
    if(lvl[a] <= lvl[b])return a ;
    return b ;
}

int query(nod *tatal, int st, int dr)
{
    ///cout << st << " " << dr << "     " << tatal -> st << " " << tatal -> dr << " " << tatal -> mid << "       " << tatal ->val << endl ;

    if(tatal -> st == st && tatal -> dr == dr)
        return tatal -> val ;

    if(dr <= tatal -> mid)
        return query(tatal -> stfiu, st, dr) ;

    if(st >= tatal -> mid + 1)
        return query(tatal -> drfiu, st, dr) ;

    return comp(query(tatal -> stfiu, st, tatal -> mid), query(tatal -> drfiu, tatal -> mid + 1, dr)) ;
}

nod tree[400009] ;

void create(int f, int st, int dr)
{
    if(st == dr)
    {
        tree[f].st = st ;
        tree[f].dr = st ;
        tree[f].mid = st ;

        tree[f].val = st ;

        return ;
    }

    int mid = (st + dr) / 2 ;

    create(2 * f, st, mid) ;
    create(2 * f + 1, mid + 1, dr) ;

    tree[f].st = st ;
    tree[f].dr = dr ;
    tree[f].mid = mid ;
    tree[f].stfiu = &tree[2 * f] ;
    tree[f].drfiu = &tree[2 * f + 1] ;

    tree[f].val = comp(tree[2 * f].val, tree[2 * f + 1].val) ;
}

int main()
{
    int n, q ;

    cin >> n >> q ;

    for(int f = 2 ; f <= n ; f ++)
        cin >> tatal[f], fii[tatal[f]].push_back(f) ;

    int neuler = peuler(1, 1, 0) - 1 ;

    for(int f = 1 ; f <= neuler ; f ++)
        if(!primaparitie[e[f]])primaparitie[e[f]] = f ;

    /// trebe dat indicele elementului minim

    create(1, 1, neuler) ;
/*
    for(int f = 1 ; f <= neuler ; f ++)
        cout << lvl[f] << " " ;

    cout << endl ;

    for(int f = 1 ; f <= neuler ; f ++)
        cout << tree[f].st << " " << tree[f].dr << "      " << tree[f].val << endl ;
*/
    while(q --)
    {
        int st, dr, a, b, mn = INT_MAX ;

        cin >> a >> b ;

        st = primaparitie[a] ;
        dr = primaparitie[b] ;

        if(st > dr)swap(st, dr) ;

        ///cout << st << " " << dr << endl ;

        cout << e[query(&tree[1], st, dr)] << '\n' ;
    }

    return 0 ;
}