Pagini recente » Rating adrian (georgiuadrian) | Cod sursa (job #60217) | Cod sursa (job #1604418) | Cod sursa (job #2503969) | Cod sursa (job #571914)
Cod sursa(job #571914)
// complexitate <O(nlog(n), O(1)>
#include<fstream>
#include<vector>
#include<iostream>
using namespace std;
const int maxn = 100010;
const int maxm = 2000010;
vector <int> v[maxn];
int nd[2*maxn+20], dn[2*maxn+20];
int tour[4*maxn+20], ap[2*maxn+20];
int significant[5*maxn];
int leftk[5*maxn], rightk[5*maxn];
vector <int> pmin[5*maxn], smin[5*maxn];
ofstream g("lca.out");
void dfs(int nod, int &i, int &k) {
i++; k++;
int actual = i;
nd[nod] = i;
dn[i] = nod;
tour[k] = i;
ap[i] = k;
for (int j = 0; j < v[nod].size(); j++) {
dfs(v[nod][j], i, k);
k++;
tour[k] = actual;
}
}
int buildTree(int pos, int dec, int &i) {
int actual;
if (pos > dec) {
i++;
actual = i;
pmin[i].push_back(tour[(i+1)/2]);
smin[i].push_back(tour[(i+1)/2]);
leftk[i] = -1;
rightk[i] = -1;
return i;
}
else {
int left_son = buildTree(2*pos, dec, i);
i++;
actual = i;
int right_son = buildTree(2*pos+1, dec, i);
leftk[actual] = left_son;
rightk[actual] = right_son;
//actualizare pmin
pmin[actual] = pmin[left_son];
int last = pmin[actual].size()-1;
for (int j = 0; j < pmin[right_son].size(); j++) {
if (pmin[right_son][j] < pmin[actual][last])
pmin[actual].push_back(pmin[right_son][j]);
else
pmin[actual].push_back(pmin[actual][last]);
last++;
}
//actualizare smin
int first = smin[right_son][0];
for (int j = 0; j < smin[left_son].size(); j++) {
if (smin[left_son][j] < first)
smin[actual].push_back(smin[left_son][j]);
else
smin[actual].push_back(first);
}
for (int j = 0; j < smin[right_son].size(); j++)
smin[actual].push_back(smin[right_son][j]);
}
return actual;
}
int treeQuery(int x, int y) {
int z = x^y;
int k = significant[z];
x = x >> k-1;
if (x % 2 == 0)
x++;
x = x << k-1;
return x;
}
int main() {
ifstream f("lca.in");
int n, m;
f >> n >> m;
int x, y;
for (int i = 2; i <= n; i++) {
f >> x;
v[x].push_back(i);
}
int number1 = 0, number2 = 0;
dfs(1, number1, number2);
int leafs = 2*n-1;
int total_leafs = 1;
while (total_leafs < leafs)
total_leafs = total_leafs*2;
int dec = total_leafs-1;
number1 = 0;
buildTree(1, dec, number1);
significant[1] = 1;
int next = 2;
for (int i = 2; i <= 2*total_leafs-1; i++) {
if (i == next) {
significant[i] = significant[i-1]+1;
next = next<<1;
}
else
significant[i] = significant[i-1];
}
int res, dx, dy, tx, ty, aux, qx, qy;
int left_son, right_son, pos_left, pos_right, minx, miny, size;
for (int i = 1; i <= m; i++) {
f >> x >> y;
if (x == y)
res = x;
else {
dx = nd[x];
dy = nd[y];
tx = ap[dx];
ty = ap[dy];
if (tx > ty) {
aux = tx;
tx = ty;
ty = aux;
}
qx = (tx-1)*2+1;
qy = (ty-1)*2+1;
res = treeQuery(qy, qx);
if (res%2 == 1)
res = dn[(res+1)/2];
else {
left_son = leftk[res];
right_son = rightk[res];
size = smin[left_son].size();
pos_left = (tx-1)%size;
pos_right = (ty-1)%size;
minx = smin[left_son][pos_left];
miny = pmin[right_son][pos_right];
if (minx < miny)
res = minx;
else res = miny;
res = dn[res];
}
}
g << res << '\n';
}
return 0;
}