Cod sursa(job #2560652)

Utilizator viftode4Iftode Vlad viftode4 Data 28 februarie 2020 10:32:50
Problema Range minimum query Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.64 kb
#include <bits/stdc++.h>
#define pb push_back
#define st first
#define nd second
using namespace std;
ifstream fin ( "lca.in" );
ofstream fout ( "lca.out" );
int rmq[400005][50], n, m;
int lg[400005];
int niv[400005];
int first[100005];
vector<int>g[100005];
vector<int>euler;
void build_rmq() {
    int k = euler.size();
    k--;

    for ( int i = 2; i <= k; i++ )
        lg[i] = lg[i / 2] + 1;

    for ( int i = 0; i <= k; i++ )
        rmq[i][0] = i;

    for ( int j = 1; j <= lg[k]; j++ )
        for ( int i = 0; i + ( 1 << ( j - 1 ) ) <= k; i++ ) {
            rmq[i][j] = rmq[i][j - 1];

            if ( niv[rmq[i][j]] > niv[rmq[i + ( 1 << ( j - 1 ) )][j - 1]] )
                rmq[i][j] = rmq[i + ( 1 << ( j - 1 ) )][j - 1];
        }
}
int query ( int l, int r ) {
    int x, y;
    x = l, y = r;
    l = min ( first[x], first[y] );
    r = max ( first[x], first[y] );
    int d = r - l  + 1;
    int k = lg[d];
    int sol = rmq[l][k];

    if ( niv[sol] > niv[rmq[r - ( 1 << k ) + 1][k]] )
        sol = rmq[r - ( 1 << k ) + 1][k];

    return euler[sol];
}
void dfs ( int x, int l ) {
    euler.pb ( x );
    niv[euler.size() - 1] = l;
    first[x] = euler.size() - 1;

    for ( auto it : g[x] ) {
        dfs ( it, l + 1 );
        euler.pb ( x );
        niv[euler.size() - 1] = l;
    }
}
int main() {
    fin >> n >> m;

    for ( int i = 1; i < n; i++ ) {
        int x;
        fin >> x;
        g[x].pb ( i + 1 );
    }

    dfs ( 1, 0 );
    build_rmq();

    while ( m-- ) {
        int x, y;
        fin >> x >> y;
        fout << query ( x, y ) << '\n';
    }

    return 0;
}