Cod sursa(job #2000951)

Utilizator savigunFeleaga Dragos-George savigun Data 15 iulie 2017 12:18:24
Problema Lowest Common Ancestor Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 3.42 kb
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;


ifstream in("lca.in");
ofstream out("lca.out");

const int MAXN = 1e5 + 5;
int n, m, nop;
int level[MAXN], parent[MAXN], whatPath[MAXN], whatPos[MAXN], size[MAXN], dp[6][MAXN], pathLevel[MAXN];
vector<int> g[MAXN], paths[MAXN];


void set_path(int x, int p) {
    whatPath[x] = p;
    whatPos[x] = paths[p].size();
    paths[p].push_back(x);
}

int get_path_parent(int x) {
    return paths[whatPath[x]][paths[whatPath[x]].size() - 1];
}

int get_path_parent_from_path(int p) {
    if (p == 0) return 0;
    return paths[p][paths[p].size() - 1];
}

void HPD(int x, int depth) {
    level[x] = depth;
    if (g[x].size() == 0) {
        size[x] = 1;
        nop++;
        set_path(x, nop);
    } else {
        int max_size = 0, max_path;
        size[x] = 1;

        for (int i = 0; i < g[x].size(); ++i) {
            int y = g[x][i];
            HPD(y, depth + 1);
            size[x] += size[y];
            if (size[y] > max_size) {
                max_size = size[y];
                max_path = whatPath[y];
            }
        }

        set_path(x, max_path);

        // set path as parent to all children paths
        for (int i = 0; i < g[x].size(); ++i) {
            int y = g[x][i];
            if (whatPath[y] != whatPath[x]) {
                dp[0][whatPath[y]] = whatPath[x];
            }
        }
    }
}

void preprocess() {
    for (int k = 1; k <= 5; ++k) {
        for (int path = 1; path <= nop; ++path) {
            dp[k][path] = dp[k-1][dp[k-1][path]];
        }
    }


     for (int k = 0; k <= 5; ++k) {
        for (int path = 1; path <= nop; ++path) {
            dp[k][path] = get_path_parent_from_path(dp[k][path]);
        }
    }
}

void set_path_level(int x, int p) {
    pathLevel[x] = p;
    for (int i = 0; i < g[x].size(); ++i) {
        int y = g[x][i];
        if (whatPath[y] != whatPath[x]) set_path_level(y, p + 1); else set_path_level(y, p);
    }
}

void levelize(int &x, int &y) {
    int xPathParent = get_path_parent(x);
    int yPathParent = get_path_parent(y);

    if (pathLevel[xPathParent] != pathLevel[yPathParent]) {
        if (pathLevel[xPathParent] < pathLevel[yPathParent]) {
            swap(x, y);
            swap(xPathParent, yPathParent);
        }

       int bit = 5;
       for (; bit >= 0; --bit) {
            if (pathLevel[dp[bit][x]] < pathLevel[y]) {
                x = dp[bit][x];
            }
       }

       x = parent[x];
    }
}

int query(int x, int y) {
    levelize(x, y);

    if (whatPath[x] == whatPath[y]) return (level[x] > level[y]) ? y : x;


    int bit = 5;
    for (; bit >= 0; --bit) {
       if (whatPath[dp[bit][whatPath[x]]] != whatPath[dp[bit][whatPath[y]]]) {
            x = dp[bit][whatPath[x]];
            y = dp[bit][whatPath[y]];
       }
    }


    int xPathParent = get_path_parent(x);
    int yPathParent = get_path_parent(y);

    return (level[xPathParent] > level[yPathParent]) ? parent[yPathParent] : parent[xPathParent];
}


int main()
{
    in >> n >> m;
    for (int i = 2, x; i <= n; ++i) {
        in >> x;
        parent[i] = x;
        g[x].push_back(i);
    }

    HPD(1, 1);

    preprocess();

    set_path_level(1, 1);

    for (int i = 1, x, y; i <= m; ++i) {
        in >> x >> y;
        out << query(x, y) << "\n";
    }

    return 0;
}