Cod sursa(job #1566995)

Utilizator TimitocArdelean Andrei Timotei Timitoc Data 12 ianuarie 2016 20:56:00
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.99 kb
#include <iostream>
#include <cstdio>
#include <vector>
#define MAXN 100100
#define MAXLOG 20

using namespace std;

vector<int> arb[MAXN];
int n, m, t[MAXN], viz[MAXN], rm[MAXLOG][2*MAXN], log[2*MAXN];
int k;
vector<int> euler;
vector<int> depth;

void citire()
{
    scanf("%d %d", &n, &m);
    for (int i = 2; i <= n; i++) {
        scanf("%d", &t[i]);
        arb[t[i]].push_back(i);
    }
    depth.push_back(-1);
    euler.push_back(-1);
}

void prepareEuler(int crt, int nivel)
{
    if (!viz[crt])
        viz[crt] = depth.size();
    depth.push_back(nivel);
    euler.push_back(crt);
    for (int i = 0, sz = arb[crt].size(); i < sz; i++) {
        prepareEuler(arb[crt][i], nivel+1);
		depth.push_back(nivel);
		euler.push_back(crt);
    }
}

void prepareRMQ()
{
	k = depth.size()-1;
	for (int i = 1; i <= k; i++)
        rm[0][i] = i;
	for (int i = 1; 1<<i <= k; i++)
		for (int j = 1; j + (1<<(i-1)) <= k; j++)
	{
        int aux = j + (1<<(i-1));
        if (depth[rm[i-1][j]] < depth[rm[i-1][aux]])
			rm[i][j] = rm[i-1][j];
		else
			rm[i][j] = rm[i-1][aux];
	}
}

void prepareLog()
{
	int crt = 1, pwr = 0;
    for (int i = 1; i <= 2*n+10; i++)
	{
        if (i >= crt<<1) crt *= 2, pwr++;
        log[i] = pwr;
	}
}

void debug()
{
    for (int i = 1; i < euler.size(); i++)
		printf("%d ", depth[i]);
	printf("\n");
	for (int i = 1; 1<<i <= k; i++, printf("\n"))
		for (int j = 1; j + (1<<(i-1)) <= k; j++)
			printf("%d ", depth[rm[i][j]]);
}

int minAncest(int x, int y)
{
	if (x > y) swap(x, y);
    int len = y-x+1, lg = log[len];
    if (depth[rm[lg][x]] < depth[rm[lg][y+1-(1<<lg)]])
		return rm[lg][x];
	return rm[lg][y+1-(1<<lg)];
}

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

    citire();
    prepareEuler(1, 0); /// Eulerian tree traversal
    prepareRMQ(); /// Prepare rmq matrix
    prepareLog();
    for (int i = 1; i <= m; i++) {
        int x, y;
        scanf("%d %d", &x, &y);
        printf("%d\n", euler[minAncest(viz[x], viz[y])]);
    }
    return 0;
}