Pagini recente » Cod sursa (job #2774949) | Cod sursa (job #1737172) | Cod sursa (job #527514) | Istoria paginii runda/road_to_ioi_7/clasament | Cod sursa (job #1119741)
#include<fstream>
#include<vector>
using namespace std;
const int INF=(1<<30)-1;
const int MAXN=100005;
const int MAX_LOG=20;
int n,m,lge;
int H[MAXN],E[2*MAXN],L[2*MAXN],logaritm[MAXN];
int RMQ[MAXN][MAX_LOG];
vector<int> G[MAXN];
ifstream fin("lca.in");
ofstream fout("lca.out");
void dfs(int u, int nivel)
{
H[u]=min(H[u], lge);
E[++lge]=u;
L[lge]=nivel;
for (vector<int>::iterator v=G[u].begin(); v!=G[u].end(); ++v)
{
dfs(*v, nivel+1);
E[++lge]=u;
L[lge]=nivel;
}
}
void rmq_preprocess()
{
/*CALCULEAZA POZITIA PE CARE O OCUPA NODUL CEL MAI
APROPIAT DE RADACINA IN VECTORUL E
DIN INTERVALUL [i,i+2^j-1]
*/
int i,j;
for (i=2; i<=lge; ++i)
logaritm[i]=logaritm[i/2]+1;
for (i=1; i<=lge; ++i)
RMQ[i][0]=i;
for (j=1; (1<<j)<=lge; ++j)
{
for (i=1; i+(1<<j)<=lge; ++i)
{
if (L[RMQ[i][j-1]]<L[RMQ[i+(1<<(j-1))][j-1]])
RMQ[i][j]=RMQ[i][j-1];
else
RMQ[i][j]=RMQ[i+(1<<(j-1))][j-1];
}
}
}
int rmq_query(int i,int j)
{
int k;
k=logaritm[j-i];
if (L[RMQ[i][k]] < L[RMQ[i+(1<<k)][k]])
return RMQ[i][k];
else
return RMQ[i+(1<<k)][k];
}
int lca(int u, int v)
{
int a=H[u], b=H[v], diff, sol;
if (a>b)
swap(a,b);
diff=b-a+1;
if (RMQ[a][logaritm[diff]] < RMQ[b-diff+1][logaritm[diff]])
sol=RMQ[a][logaritm[diff]];
else
sol=RMQ[b-diff+1][logaritm[diff]];
return E[sol];
}
int main()
{
int i,x,y;
fin>>n>>m;
for (i=2; i<=n; ++i)
{
fin>>x;
G[x].push_back(i);
}
for (i=1; i<=2*n; H[i]=INF, ++i);
dfs(1,0);
rmq_preprocess();
for (i=1; i<=m; ++i)
{
fin>>x>>y;
fout<<lca(x,y)<<'\n';
}
return 0;
}