Cod sursa(job #2001021)

Utilizator savigunFeleaga Dragos-George savigun Data 15 iulie 2017 15:10:23
Problema Lowest Common Ancestor Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 3.65 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], log[MAXN];
vector<int> g[MAXN], paths[MAXN];


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

inline int get_path_parent(int x) {
    return paths[whatPath[x]].back();
}

inline int get_path_parent_from_path(int p) {
    if (p == 0) return 0;
    return paths[p].back();
}

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() {
    int lg = 0;
    int next = 2;
    for (int i = 1; i <= n; ++i) {
        if (i == next) {
            lg++;
            next *= 2;
        }
        log[i] = lg;
    }

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


    for (int k = 0; k <= 3; ++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) {
    if (pathLevel[x] != pathLevel[y]) {
        int xPathParent = get_path_parent(x);
        int yPathParent = get_path_parent(y);
        if (pathLevel[xPathParent] < pathLevel[yPathParent]) {
            swap(x, y);
            swap(xPathParent, yPathParent);
        }

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

        x = parent[get_path_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 = log[pathLevel[x]];
    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;
}