Pagini recente » Clasament cls_7_8_simulare_oji | Cod sursa (job #2243310) | Cod sursa (job #610411) | Cod sursa (job #1584920) | Cod sursa (job #2001025)
#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;
}