Pagini recente » Cod sursa (job #548610) | Cod sursa (job #2636302) | Cod sursa (job #1784134) | Cod sursa (job #2255105) | Cod sursa (job #1967637)
#include <stdint.h>
#include <fstream>
#include <math.h>
#define nmax 100001
#define mmax 2000001
#define log2l 18
#define sqrtn 450
using namespace std;
fstream f1("lca.in", ios::in);
fstream f2("lca.out", ios::out);
int32_t n, m, t[nmax], ha[nmax*2], eu[nmax*2], nr, first[nmax], lung;
int32_t a[2*nmax][log2l+1];
int32_t put2[log2l+1];
///first[i]= indicele primei aparitii a nodului i in parcurgerea euler (eu)
///lca(x,y)= nodul din eu care este cuprins intre first[x] si first[y] si are ha[i] minim
///a[i][j]= minimul din vect ha, care incepe de pe pozitia i si contine 2^j elemente
void citire()
{
int32_t i;
f1>>n>>m;
for(i=2; i<=n; i++)
f1>>t[i];
///1= radacina
}
int32_t minim(int32_t a, int32_t b)
{
if(a<b) return a;
else return b;
}
int32_t query(int32_t l, int32_t r)
{
int32_t j=log2(r-l+1), v1, v2;
v1=a[l][j];
v2=a[r-put2[j]+1][j];
if(ha[v1]<ha[v2]) return v1;
else return v2;
///a[l][j] aproape echivalent cu a[r-pow(2, j)+1][j]
///le folosesti pe amandoua pt a det minimul cu exactitate (pierderi la log2)
}
void afisare()
{
int32_t i, x, y, a, b;
for(i=1; i<=m; i++)
{
f1>>x>>y;
a=first[x];
b=first[y];
if(a>b) swap(a, b);
f2<<eu[query(a, b)]<<"\n";///minim intervalul a,b
///lca(x,y);
}
}
void euler(int32_t rad, int32_t h)
{
int32_t i;
nr++;
eu[nr]=rad;
ha[nr]=h;
for(i=1; i<=n; i++)
if(t[i]==rad)
{
euler(i, h+1);
nr++;
eu[nr]=rad;
ha[nr]=h;
}
}
void first_v()
{
int32_t i;
lung=2*n-1;
for(i=1; i<=lung; i++)
if(!first[eu[i]]) first[eu[i]]=i;
}
void rmq()
{
int32_t i, j;
for(i=1; i<=lung; i++)
a[i][0]=i;
for(j=1; j<=log2l; j++)
for(i=1; i<=(lung-put2[j]); i++)
if(ha[a[i][j-1]] < ha[a[i+put2[j-1]][j-1]]) a[i][j]=a[i][j-1];
else a[i][j]=a[i+put2[j-1]][j-1];
}
void putere()
{
int32_t i;
put2[0]=1;
put2[1]=2;
for(i=2; i<=log2l; i++)
put2[i]=put2[i-1]*2;
}
int main()
{
citire();
euler(1, 0);
first_v();
putere();
rmq();///range minimum query
afisare();
return 0;
}