Cod sursa(job #1479807)

Utilizator AlexNiuclaeNiculae Alexandru Vlad AlexNiuclae Data 1 septembrie 2015 12:58:28
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.59 kb
#include <bits/stdc++.h>

#define F first
#define S second

using namespace std;

const int Nmax = 100000 + 10;

int n , m , i;
int first[Nmax] , Log[Nmax<<1];
vector < int > g[Nmax];

vector < pair < int , int > > d[18];

void euler(int node , int lvl)
{
    d[0].push_back({lvl , node});
    first[node] = d[0].size() - 1;

    for (auto &it : g[node])
    {
        euler(it , lvl+1);
        d[0].push_back({lvl , node});
    }
}

void makeRmq()
{
    int i , j , n = d[0].size() - 1;

    for (i = 2; i <= n; ++i) Log[i] = Log[i>>1] + 1;

    for (i = 1; i <= Log[n]; ++i)
    {
        d[i].push_back({0,0});
        for (j = 1; j <= n - (1<<i) + 1; ++j)
        {
            d[i].push_back({0,0});
            d[i][j] = (d[i-1][j].F <= d[i-1][j+(1<<(i-1))].F) ? d[i-1][j] : d[i-1][j+(1<<(i-1))];
        }
    }
}

int main()
{
    freopen("lca.in","r",stdin);
    freopen("lca.out","w",stdout);

    scanf("%d %d", &n, &m);

    for (i = 2; i <= n; ++i)
    {
        int dad;
        scanf("%d", &dad);
        g[dad].push_back(i);
    }

    d[0].push_back({0,0});
    euler(1 , 1);
    makeRmq();

    for (i = 1; i <= m; ++i)
    {
        int node1 , node2 , left , right , k;
        scanf("%d %d", &node1, &node2);

        left = first[node1]; right = first[node2];
        if (left > right) swap(left , right);
        k = Log[right - left + 1];

        if (d[k][left].F < d[k][right-(1<<k)+1].F)
            printf("%d\n", d[k][left].S);
        else
            printf("%d\n", d[k][right-(1<<k)+1].S);
    }

    return 0;
}