Cod sursa(job #2287500)

Utilizator danielsociuSociu Daniel danielsociu Data 21 noiembrie 2018 22:52:44
Problema Lowest Common Ancestor Scor 30
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.34 kb
#include <fstream>
#include <vector>
std::ifstream cin("lca.in");
std::ofstream cout("lca.out");
#define it std::vector<int>::iterator
#define maxn 100005
int lg[maxn],l[maxn<<1],euler[maxn<<1],prim[maxn<<1];
int rmq[20][maxn<<2],k,n,m;
std::vector<int> g[maxn];

void dfs(int x,int lv){
    euler[++k]=x;
    l[k]=lv;
    prim[x]=k;
    for(it xd=g[x].begin();xd!=g[x].end();++xd){
        dfs(*xd,lv+1);
        euler[++k]=x;
        l[k]=lv;
    }
}
void RMQ(){
    int i,j;
    for(i=2;i<=k;i++)
        lg[i]=lg[i>>1]+1;
    for(i=1;i<=k;i++)
        rmq[0][i]=i;
    for(i=1;(1<<i)<k;i++)
        for(j=1;j<=k-(1<<i);j++){
            int L=1<<(i-1);
            rmq[i][j]=rmq[i-1][j];
            if(l[rmq[i-1][j]]>l[rmq[i-1][j+L]])
                rmq[i][j]=rmq[i-1][j+L];
    }
}
int lca(int x,int y){
    int a,b,diff,sh,sol;
    a=prim[x],b=prim[y];
    if(a>b)
        a+=b,b=a-b,a-=b;
    diff=b-a+1;
    sh=diff-(1<<lg[diff]);
    sol=rmq[lg[diff]][a];
    if(l[rmq[lg[diff]][a]]>l[rmq[lg[diff]][a+sh]])
        sol=rmq[lg[diff]][a+sh];
    return euler[sol];
}

int main()
{
    int x,y;
    cin>>n>>m;
    for(int i=2;i<=n;i++){
        cin>>x;
        g[x].push_back(i);
    }
    dfs(1,0);
    RMQ();
    for(;m--;){
        cin>>x>>y;
        cout<<lca(x,y)<<'\n';
    }
    return 0;
}