Cod sursa(job #1804519)

Utilizator delia_ioanaCeapa Delia Ioana delia_ioana Data 12 noiembrie 2016 17:44:34
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.78 kb
#include <iostream>
#include <vector>
#include <math.h>
#include <stdio.h>
#include <utility>
#include <stdlib.h>

using namespace std;
#define max_n 100005

vector<int> first(max_n), euler_nodes, euler_levels;
vector<vector<int> > child(max_n), rmq;
int n, m, a;

void make_euler(int node, int level) {
    euler_nodes.push_back(node);
    euler_levels.push_back(level);
    first[node] = euler_nodes.size() - 1;

    for (int i = 0; i < child[node].size(); i ++) {
        make_euler(child[node][i], level + 1);
        euler_nodes.push_back(node);
        euler_levels.push_back(level);
    }
}

void make_rmq() {
    int s = euler_levels.size();
    int l = (int)(log(s) / log(2));

    vector<int> t(l + 1);

    for (int i = 0; i < s; i ++)
        rmq.push_back(t);

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

    for (int j = 1; j <= l; j ++) 
        for (int i = 0; i < s - (1 << (j - 1)); i ++)
            rmq[i][j] = (euler_levels[rmq[i][j - 1]] < euler_levels[rmq[i + (1 << (j - 1))][j - 1]] ? rmq[i][j - 1] : rmq[i + (1 << (j - 1))][j - 1]);
}

int main() {
    freopen("lca.in", "r", stdin);
    freopen("lca.out", "w", stdout);
    
    scanf("%d %d", &n, &m);
    for (int i = 0; i < n - 1; i ++) {
    	scanf("%d", &a);
        child[a].push_back(i + 2);
    }

    make_euler(1, 0);
    make_rmq();

    for (int i = 0; i < m; i ++) {
        int n1, n2;
        scanf("%d %d", &n1, &n2);

        int r1 = first[n1], r2 = first[n2];
        int range = abs(r2 - r1) + 1, lr = (int)(log(range) / log(2));
        int sol = rmq[min(r1, r2)][lr];

        range -= (1 << lr);
        if (range != 0)
            sol = (euler_levels[sol] < euler_levels[rmq[min(r1, r2) + range][lr]] ? sol : rmq[min(r1, r2) + range][lr]);
        printf("%d\n", euler_nodes[sol]);
    }

    return 0;
}