Pagini recente » Cod sursa (job #1220879) | Cod sursa (job #465540) | Cod sursa (job #597941) | Diferente pentru home intre reviziile 469 si 468 | Cod sursa (job #731025)
Cod sursa(job #731025)
//Voroneanu Radu
//LCA - folosind rmq pe grupe de lungimi (log N / 2)
//Complexitate : O(N+M)
//Memorie : O(N)
//Timp de lucru : 60 min
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <string.h>
using namespace std;
#define MAXN 100002
#define MAXLOG 16
#define MAXG 12
int Lv[MAXN], T[MAXN], First[MAXN], Grup[MAXN], lg[MAXN];
int Q[MAXN*2];
vector<int> G[MAXN];
int N, M, E;
int i, x, y;
int Ans;
int P[(1<<MAXG)][MAXG][MAXG];
int RMQ[MAXLOG][2*MAXN/MAXG + 2];
void df(int nod)
{
vector<int>::iterator it;
Lv[nod] = Lv[T[nod]] + 1;
Q[++E] = nod;
First[nod] = E;
for (it = G[nod].begin(); it != G[nod].end(); ++it){
df(*it);
Q[++E] = nod;
Grup[E/MAXG] |= (1<<(E%MAXG));
}
}
inline void precalcul()
{
int mask, i, j, minim;
int Nr[MAXG];
memset(Nr, 0, sizeof(Nr));
for (mask = 0; mask < (1<<MAXG); ++mask)
for (i = 0; i < MAXG; ++i){
Nr[i] = 0; minim = i;
P[mask][i][i] = i;
for (j = i+1; j < MAXG; ++j){
if (mask & (1<<j))
Nr[j] = Nr[j-1] - 1;
else
Nr[j] = Nr[j-1] + 1;
if (Nr[minim] > Nr[j])
minim = j;
P[mask][i][j] = minim;
}
}
}
inline void rmq_grupe()
{
int i, j, l, W;
W = (E / MAXG) + 1;
lg[1] = 0;
for (i = 2; i < W; ++i)
lg[i] = lg[i>>1] + 1;
for (i = 0; i < W; ++i)
RMQ[0][i] = Q[P[Grup[i]][0][MAXG-1] + i * MAXG];
for (i = 1; (1<<i) <= W; ++i)
for (j = 0; j < W - (1<<i) + 1; ++j)
{
l = 1<<(i-1);
RMQ[i][j] = RMQ[i-1][j];
if (Lv[ RMQ[i][j] ] > Lv[ RMQ[i-1][j+l] ])
RMQ[i][j] = RMQ[i-1][j+l];
}
}
inline void rmq(int x, int y)
{
int diff, l, sh;
if (x > y)
swap(x,y);
if (x / MAXG == y / MAXG){
Ans = Q[ P[Grup[x/MAXG]][x%MAXG][y%MAXG] + (x/MAXG)*MAXG];
return;
}
int grupx, grupy;
grupx = x / MAXG;
grupy = y / MAXG;
if (Lv[Ans] > Lv[ Q[ P[Grup[grupx]][x%MAXG][MAXG-1] + grupx * MAXG ] ] )
Ans = Q[ P[Grup[grupx]][x%MAXG][MAXG-1] + grupx * MAXG ];
if (Lv[Ans] > Lv[ Q[ P[Grup[grupy]][0][y%MAXG] + grupy * MAXG ] ] )
Ans = Q[ P[Grup[grupy]][0][y%MAXG] + grupy * MAXG ];
x = x / MAXG + 1;
y = y / MAXG - 1;
if (x <= y){
diff = y - x + 1;
l = lg[diff];
sh = diff - (1<<l);
if (Lv[Ans] > Lv[ RMQ[l][x] ])
Ans = RMQ[l][x];
if (Lv[Ans] > Lv[ RMQ[l][x + sh] ])
Ans = RMQ[l][x + sh];
}
}
int main()
{
freopen("lca.in","r",stdin);
freopen("lca.out","w",stdout);
scanf("%d %d",&N,&M);
for (i = 2; i <= N; ++i){
scanf("%d",&T[i]);
G[T[i]].push_back(i);
}
E = -1;
df(1);
precalcul();
rmq_grupe();
for (i = 1; i <= M; ++i){
scanf("%d %d",&x,&y);
Ans = x;
rmq(First[x], First[y]);
printf("%d\n",Ans);
}
return 0;
}