Pagini recente » Monitorul de evaluare | Cod sursa (job #57373) | Cod sursa (job #688646) | Cod sursa (job #2576909) | Cod sursa (job #1183257)
#include<iostream>
#include<fstream>
#include<vector>
#include<algorithm>
using namespace std;
ifstream in("lca.in");
ofstream out("lca.out");
const int N = 101000;
const int SIZ = 9;
int n, m, e[2 * N], nr, cs[N];
int minLeft[1<<SIZ][SIZ], minRight[1<<SIZ][SIZ], pozminLeft[1<<SIZ][SIZ], pozminRight[1<<SIZ][SIZ];
int niv[N];
vector<int> v[N];
int valNr1[N], tip[N], pozB[N];
void eul(int nod) {
e[++nr] = nod;
cs[nod] = nr;
for(vector<int>::iterator it = v[nod].begin(); it != v[nod].end(); ++it) {
niv[*it] = niv[nod] + 1;
eul(*it);
e[++nr] = nod;
}
}
void precalc1() {
int i, j;
for(i = 0; i < (1<<SIZ); ++i) {
int boss = 0;
for(j = 0; j < SIZ; ++j) {
if(i & (1<<j))
++boss;
else
--boss;
minLeft[i][j] = boss;
pozminLeft[i][j] = j;
if(j && minLeft[i][j - 1] > boss) {
minLeft[i][j] = minLeft[i][j - 1];
pozminLeft[i][j] = pozminLeft[i][j - 1];
}
}
boss = 0;
for(j = SIZ - 1; j >= 0; --j) {
if(i & (1<<j))
++boss;
else
--boss;
minRight[i][j] = boss;
pozminRight[i][j] = j;
if(j != SIZ - 1 && minRight[i][j + 1] > boss) {
minRight[i][j] = minRight[i][j + 1];
pozminRight[i][j] = pozminRight[i][j + 1];
}
}
}
}
void precalc2() {
int i, j;
for(i = 1; i <= nr; ++i) {
if(i % 10 == 1) {
pozB[i] = -1;
int ti = 0;
valNr1[i] = niv[e[i]];
for(j = i + 1; j < i + 10; ++j)
if(niv[j] > niv[j - 1])
ti |= (1<<(j - i - 1));
}
else {
valNr1[i] = valNr1[i - 1];
tip[i] = tip[i - 1];
pozB[i] = pozB[i - 1] + 1;
}
}
for(i = 1; i <= nr; ++i)
if(pozB[i] == -1)
pozB[i] = 0;
}
int rmq[15][N], elMin[15][N], p2[N];
void precalc3() {
int i, j;
int nu = 0;
for(i = 2; i < N; ++i)
p2[i] = p2[i / 2] + 1;
for(i = 1; i <= nr; ++i) {
if(i % 10 == 1) {
int nivv = 1000000, nodd;
for(j = i; j < i + 10; ++j) {
if(niv[e[j]] < nivv) {
nodd = e[j];
nivv = niv[e[j]];
}
}
rmq[0][++nu] = nivv;
elMin[0][nu] = nodd;
}
}
for(i = 1; i < 15; ++i) {
for(j = 1; j <= nr - (1<<i); ++j) {
int l = (1<<(i - 1));
if(rmq[i - 1][j] < rmq[i - 1][j + l]) {
rmq[i][j] = rmq[i - 1][j];
elMin[i][j] = elMin[i - 1][j];
}
else {
rmq[i][j] = rmq[i - 1][j + l];
elMin[i][j] = elMin[i - 1][j + l];
}
}
}
}
int lca(int nod1, int nod2) {
int nivmin, elmin;
if(niv[nod1] > niv[nod2]) {
nivmin = niv[nod2];
elmin = nod2;
}
else {
nivmin = niv[nod1];
elmin = nod1;
}
if(cs[nod1] > cs[nod2])
swap(nod1, nod2);
//yolo
if(cs[nod2] - cs[nod1] <= 10) {
int nmin = 10000000, ell;
for(int i = cs[nod1]; i <= cs[nod2]; ++i) {
if(niv[e[i]] < nmin) {
nmin = niv[e[i]];
ell = e[i];
}
}
return ell;
}
//
nod1 = cs[nod1];
nod2 = cs[nod2];
if(valNr1[nod1] + minRight[tip[nod1]][pozB[nod1]] < nivmin) {
nivmin = valNr1[nod1] + minRight[tip[nod1]][pozB[nod1]];
elmin = e[pozminRight[tip[nod1]][pozB[nod1]]];
}
if(nod2 % 10 != 1 && valNr1[nod2] + minLeft[tip[nod2]][pozB[nod2]] < nivmin) {
nivmin = valNr1[nod2] + minLeft[tip[nod2]][pozB[nod2]];
elmin = e[pozminLeft[tip[nod2]][pozB[nod2]]];
}
//calc3
int poz1, poz2;
poz1 = (nod1 - 1) / 10 + 2;
poz2 = (nod2 - 1) / 10 + 2;
int l = p2[poz2 - poz1];
if(rmq[l][poz1] < nivmin) {
nivmin = rmq[l][poz1];
elmin = elMin[l][poz1];
}
if(rmq[l][poz2 - (1<<l) + 1] < nivmin) {
nivmin = rmq[l][poz2 - (1<<l) + 1];
elmin = elMin[l][poz2 - (1<<l) + 1];
}
return elmin;
}
int main() {
int i;
in >> n >> m;
for(i = 1; i < n; ++i) {
int a;
in >> a;
v[a].push_back(i + 1);
}
eul(1);
precalc1();
precalc2();
precalc3();
for(i = 1; i <= m; ++i) {
int c1, c2;
in >> c1 >> c2;
out << lca(c1, c2) << "\n";
}
return 0;
}