Pagini recente » Cod sursa (job #841185) | Cod sursa (job #1798029) | Cod sursa (job #129702) | Cod sursa (job #2058727) | Cod sursa (job #2009460)
#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
#include <cmath>
#define endl '\n'
using namespace std;
ifstream in("lca.in");
ofstream out("lca.out");
int const nmax = 100000;
int const logmax = 18;
vector<int> g[1 + nmax];
int n, m, root;
int depth[1 + nmax], inv[1 + nmax];
int v[1 + 2 * nmax], nv;
int rmq[1 + 2 * nmax][logmax];
int pow2[logmax];
void eulercircuit() {
fill(depth + 1, depth + n + 1, -1);
stack<int> st;
st.push(root);
depth[root] = 0;
while (!st.empty()) {
int from = st.top();
v[++nv] = from;
inv[from] = nv;
if (0 < g[from].size()) {
int to = g[from].back();
if (depth[to] < 0)
depth[to] = depth[from] + 1;
st.push(to);
g[from].pop_back();
} else {
st.pop();
}
}
}
void computermq() {
int range = 1, x = 0; //range = 2^x
pow2[0] = 1;
int from = 1;
while (from < nv) {
if (depth[v[from]] < depth[v[from + 1]])
rmq[from][0] = from;
else
rmq[from][0] = from + 1;
from++;
}
while ((range << 1) < nv) {
range = (range << 1);
x++;
pow2[x] = range;
from = 1;
while (from + range <= nv) {
int i = rmq[from][x - 1];
int j = rmq[from + range - pow2[x - 1]][x - 1];
// if (x == 1 && from == 10)
// cout << "D " << i << " " << j << endl;
if (depth[v[i]] < depth[v[j]])
rmq[from][x] = i;
else
rmq[from][x] = j;
from++;
}
}
// cout << rmq[10][0] << " " << rmq[10][1] << " " << rmq[10][2] << endl;
while ((range << 1) < (nmax << 1)) {
range = (range << 1);
x++;
pow2[x] = range;
}
}
int computelog(int size) {
if (size <= 4)
return 0;
else if (pow2[logmax - 1] < size)
return (logmax - 1);
else {
int lim1 = 0;
int lim2 = logmax - 1;
while (lim1 + 1 < lim2) {
int mid = ((lim1 + lim2) >> 1);
if (pow2[mid + 1] + 2 < size)
lim1 = mid;
else
lim2 = mid;
}
return lim2;
}
}
int query(int from, int to) {
if (from == to)
return from;
else {
if (to < from)
swap(from, to);
int log = computelog(to - from + 1);
int answer = min(rmq[from][log], rmq[to - pow2[log]][log]);
// cout << from << " & " << to << " with log = " << log << " -> " << v[answer] << endl;
return v[answer];
}
}
int main() {
root = 1;
in >> n >> m;
for (int i = 2; i <= n; i++) {
int dad;
in >> dad;
g[dad].push_back(i);
}
eulercircuit();
// for (int i = 1; i <= nv; i++)
// cout << v[i] << " ";
// cout << endl;
computermq();
for (int i = 1; i <= m; i++) {
int from, to;
in >> from >> to;
out << query(inv[from], inv[to]) << endl;
}
return 0;
}