Pagini recente » Cod sursa (job #2856617) | Cod sursa (job #1550811) | Cod sursa (job #1668184) | Cod sursa (job #764375) | Cod sursa (job #2093607)
#include <cstdio>
#include <vector>
#include <cmath>
#include <stack>
using namespace std;
class In_Pars {
public:
In_Pars(const char *name) {
in = fopen(name, "r");
buff = new char[4096];
index = 4095;
}
void operator >> (int &n) {
char c;
c = read_char();
while (c < '0' or c > '9') {
c = read_char();
}
n = 0;
while (c >= '0' and c <= '9') {
n = n * 10 + c - '0';
c = read_char();
}
}
private:
FILE *in;
char *buff;
int index;
char read_char() {
index ++;
if (index == 4096) {
index = 0;
fread(buff, 1, 4096, in);
}
return buff[index];
}
};
In_Pars in("lca.in");
class Hpd {
public:
Hpd() {
in >> n;
in >> m;
_chain.resize(n + 1);
_level.resize(n + 1);
_chain_lvl.resize(n + 1);
_tata.resize(n + 1);
_chain_of.resize(n + 1);
_weight.resize(n + 1);
_gr.resize(n + 1);
freopen("lca.out", "w", stdout);
for (int i = 2; i <= n; i ++) {
in >> _tata[i];
_gr[_tata[i]].push_back(i);
}
_Init();
_Set_lvl();
_Init_dp();
}
void Solve() {
int x, y;
for (int i = 1; i <= m; i ++) {
in >> x;
in >> y;
if (_chain_lvl[x] > _chain_lvl[y]) {
swap(x, y);
}
int dif = _chain_lvl[y] - _chain_lvl[x];
int bit = 0;
while (dif) {
if (dif & 1) {
y = _dp[bit][y];
}
dif >>= 1;
bit += 1;
}
for (int i = lim; i >= 0; i --) {
if (_chain_of[_dp[i][x]] != _chain_of[_dp[i][y]]) {
x = _dp[i][x];
y = _dp[i][y];
}
}
if (_chain_of[x] != _chain_of[y]) {
x = _dp[0][x];
y = _dp[0][y];
}
if (_level[x] >= _level[y]) {
printf("%d\n", y);
}
else {
printf("%d\n", x);
}
}
}
private:
int n, m, max_chain_nr, lim, max_chain_lvl;
vector < int > _level, _chain_of, _weight, _tata, _chain_lvl;
vector < vector < int > > _chain, _gr, _dp;
stack < pair < int, int > > st;
void _Init() {
st.push({1, 0});
_level[1] = 1;
max_chain_nr = 0;
for (int i = 1; i <= n; i ++) {
_weight[i] = 1;
}
while (not st.empty()) {
auto cur = st.top();
st.pop();
if (not _gr[cur.first].size()) {
_chain[++ max_chain_nr].push_back(cur.first);
_chain_of[cur.first] = max_chain_nr;
}
else if (cur.second + 1 <= (int) _gr[cur.first].size()) {
int next_node = _gr[cur.first][cur.second];
_level[next_node] = _level[cur.first] + 1;
st.push({cur.first, cur.second + 1});
st.push({next_node, 0});
}
else {
int best = 0;
for (auto x : _gr[cur.first]) {
_weight[cur.first] += _weight[x];
if (_weight[x] > _weight[best]) {
best = x;
}
}
_chain[_chain_of[best]].push_back(cur.first);
_chain_of[cur.first] = _chain_of[best];
}
}
}
void _Set_lvl() {
st.push({1, 0});
_chain_lvl[1] = 1;
max_chain_lvl = 1;
while (not st.empty()) {
auto cur = st.top();
st.pop();
max_chain_lvl = max(max_chain_lvl, _chain_lvl[cur.first]);
if (cur.second + 1 <= (int) _gr[cur.first].size()) {
int next_node = _gr[cur.first][cur.second];
st.push({cur.first, cur.second + 1});
if (_chain_of[next_node] != _chain_of[cur.first]) {
_chain_lvl[next_node] = _chain_lvl[cur.first] + 1;
}
else {
_chain_lvl[next_node] = _chain_lvl[cur.first];
}
st.push({next_node, 0});
}
}
}
void _Init_dp() {
lim = log2(max_chain_lvl);
_dp.resize(lim + 1);
for (auto &x : _dp) {
x.resize(n + 1);
}
for (int i = 1; i <= n; i ++) {
_dp[0][i] = _tata[_chain[_chain_of[i]].back()];
}
for (int i = 1; i <= lim; i ++) {
for (int j = 1; j <= n; j ++) {
_dp[i][j] = _dp[i - 1][_dp[i - 1][j]];
}
}
}
};
int main() {
Hpd *H = new Hpd();
H -> Solve();
}