Cod sursa(job #2308204)

Utilizator caesar2001Stoica Alexandru caesar2001 Data 26 decembrie 2018 16:59:58
Problema Lowest Common Ancestor Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.89 kb
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cmath>
#include <climits>

using namespace std;

const int NMAX = 100000;

vector<int> g[NMAX + 5], gp[NMAX + 5];
int dim[NMAX + 5], dad[NMAX + 5], lvl[NMAX + 5];
int path[NMAX + 5], npaths, path_dad[NMAX + 5], h[NMAX + 5];

void dfs(int node) {
    dim[node] = 1;
    int from, mx = -1;

    for(auto it : g[node])
        if(it != dad[node]) {
            lvl[it] = lvl[node] + 1;
            dfs(it);
            dim[node] += dim[it];

            if(dim[it] > mx) {
                mx = dim[it];
                from = it;
            }
        }

    if(dim[node] == 1) {
        npaths ++;
        path_dad[npaths] = node;
        path[node] = npaths;
    } else {
        path_dad[path[from]] = node;
        path[node] = path[from];
    }
}

void computeh(int node, int d) {
    for(auto it : gp[node])
        if(it != d) {
            h[it] = h[node] + 1;
            computeh(it, node);
        }
}


int readInt () {
	bool minus = false;
	int result = 0;
	char ch;
	ch = getchar();
	while (true) {
		if (ch == '-') break;
		if (ch >= '0' && ch <= '9') break;
		ch = getchar();
	}
	if (ch == '-') minus = true; else result = ch-'0';
	while (true) {
		ch = getchar();
		if (ch < '0' || ch > '9') break;
        result = result*10 + (ch - '0');
	}
	if (minus)
		return -result;
	else
		return result;
}

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

    int n, m;
    n = readInt();
    m = readInt();
    for(int i = 2; i <= n; i ++) {
        int x;
        x = readInt();

        dad[i] = x;
        g[x].push_back(i);
        g[i].push_back(x);
    }

    dim[1] = 1;
    lvl[1] = 1;
    dfs(1);

    int start = 1;
    for(int i = 1; i <= npaths; i ++) {
        if(dad[path_dad[i]] != 0) {
            gp[i].push_back(path[dad[path_dad[i]]]);
            gp[path[dad[path_dad[i]]]].push_back(i);
        } else
            start = i;
    }
    h[start] = 1;
    computeh(start, 0);

    vector<int> lg(n + 1, 0);
    for(int i = 2; i <= n; i ++)
        lg[i] = lg[i >> 1] + 1;

    vector<vector<int>> dp(lg[npaths] + 1, vector<int> (npaths + 1, 0));
    vector<vector<int>> dp2(lg[npaths] + 1, vector<int> (npaths + 1, 0));
    for(int i = 1; i <= npaths; i ++) {
        dp[0][i] = path[dad[path_dad[i]]];
        dp2[0][i] = dad[path_dad[i]];
    }

    for(int i = 1; i <= lg[npaths]; i ++)
        for(int j = 1; j <= npaths; j ++) {
            dp[i][j] = dp[i - 1][dp[i - 1][j]];
            dp2[i][j] = dp2[i - 1][dp[i - 1][j]];
        }

    for(int i = 1; i <= m; i ++) {
        int x, y;
        x = readInt();
        y = readInt();
        if(h[path[x]] < h[path[y]])
            swap(x, y);

        int pathx = path[x], pathy = path[y];
        int aux;
        if(lvl[x] > lvl[y])
            aux = y;
        else
            aux = x;


        for(int step = lg[npaths]; step >= 0; step --)
            if(dp[step][pathx] != 0 && h[pathy] <= h[dp[step][pathx]]) {
                aux = dp2[step][pathx];
                pathx = dp[step][pathx];
            }

        int ans;

        if(pathx != pathy) {
            for(int step = lg[npaths]; step >= 0; step --)
                if(dp[step][pathx] != 0 && dp[step][pathy] != 0 && dp[step][pathx] != dp[step][pathy]) {
                    pathx = dp[step][pathx];
                    pathy = dp[step][pathy];
                }

            int auxx = dp2[0][pathx];
            int auxy = dp2[0][pathy];
            if(lvl[auxx] > lvl[auxy])
                ans = auxy;
            else
                ans = auxx;

        } else {
            if(lvl[aux] < lvl[y])
                ans = aux;
            else
                ans = y;
        }

        printf("%d\n", ans);
    }

    return 0;
}