Cod sursa(job #2080191)

Utilizator xkz01X.K.Z. xkz01 Data 2 decembrie 2017 15:58:07
Problema Lowest Common Ancestor Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 1.43 kb
#include<cstdio>
#include<vector>
#include<algorithm>
#define f first
#define s second
#define NMAX 100001
using namespace std;
vector<int> a[NMAX];
int i, nrElem, k, x, y, rmq[18][2*NMAX], lgParc, lvl[NMAX], firstAp[NMAX], lg[NMAX];
int min_euler(int x, int y){
    if (lvl[x]<=lvl[y]) return x; else return y;
}
void parcurge_euler(int poz, int niv){
    vector<int>::iterator it;
    rmq[0][++lgParc]=poz; lvl[poz]=niv; firstAp[poz]=lgParc;
    for (it=a[poz].begin();it!=a[poz].end();++it) {
        parcurge_euler(*it, niv+1);
        rmq[0][++lgParc]=poz;
    }
}
void make_rmq(){
    int i, j;
    ///rmq[x][y]=minimul pe intervalul[x, x+2^y-1]
    for (i=1;(1<<i)<=lgParc;++i)
        for (j=1;j+(1<<(i-1))<=lgParc;++j) {
            rmq[i][j]=min_euler(rmq[i-1][j], rmq[i-1][j+(1<<(i-1))]);
        }
}
int lca(int x, int y){
    if (x>y) swap(x,y);
    int d=lg[y-x+1]-1;
    return min_euler(rmq[d][x], rmq[d][y-(1<<d)+1]);
}
int main(){
    freopen("lca.in","r",stdin);
    freopen("lca.out","w",stdout);
    scanf("%d%d", &nrElem, &k);
    for (i=2;i<=nrElem;++i) {
        scanf("%d", &x); a[x].push_back(i);
    }
    lgParc=0; parcurge_euler(1, 0);
    lg[1]=1; for (i=2;i<=lgParc;i++) lg[i]=lg[i>>1]+1;
    make_rmq();
    for (i=1;i<=k;i++) {
        scanf("%d%d", &x, &y);
        if (x==y) {printf("%d\n", x); continue;}
        printf("%d\n", lca(firstAp[x],firstAp[y]));
    }
    return 0;
}