Cod sursa(job #2001025)

Utilizator savigunFeleaga Dragos-George savigun Data 15 iulie 2017 15:21:16
Problema Lowest Common Ancestor Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.67 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[whatPath[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 xPath = whatPath[x];
    int yPath = whatPath[y];
    if (pathLevel[xPath] != pathLevel[yPath]) {
        if (pathLevel[xPath] < pathLevel[yPath]) {
            swap(x, y);
            swap(xPath, yPath);
        }

        int bit = log[pathLevel[xPath]];
        for (; bit >= 0; --bit) {
            if (pathLevel[dp[bit][xPath]] > pathLevel[yPath]) {
                xPath = dp[bit][xPath];
            }
        }

        x = parent[get_path_parent_from_path(xPath)];
    }
}

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

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

    int xPath = whatPath[x];
    int yPath = whatPath[y];

    int bit = log[xPath];
    for (; bit >= 0; --bit) {
       if (dp[bit][xPath] != dp[bit][yPath]) {
            xPath = dp[bit][xPath];
            yPath = dp[bit][yPath];
       }
    }

    int xPathParent = get_path_parent_from_path(xPath);
    int yPathParent = get_path_parent_from_path(yPath);

    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;
}