Cod sursa(job #3228467)

Utilizator Bogdan345Marius Mihalache Bogdan345 Data 8 mai 2024 12:39:32
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.31 kb
/*
//trebuie sa stiu
//pozitia nodului
//nivelul nodului
//fac rmq pe sirul care este
//turul lui euler
//in dp[i][j] retin nodul de pe nivelul cel mai mic
//[i,i+2^j-1]
#include <fstream>
#include <vector>
using namespace std;
ifstream cin("lca.in");
ofstream cout("lca.out");
const int MAXVAL=200000,putere=17,val=100000;
int dp[MAXVAL+1][putere+1],nivel[val+1],poz[val+1],log_2[MAXVAL+1];
vector<vector<int>>gr(val+1);
vector<int>euler;
void dfs(const int& nod){
    euler.push_back(nod);
    poz[nod]=euler.size()-1;
    for(const auto&x:gr[nod]){
        nivel[x]=nivel[nod]+1;
        dfs(x);
        euler.push_back(nod);
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n,m,nr;
    cin>>n>>m;
    for(int i=2;i<=n;i++){
        cin>>nr;
        gr[nr].push_back(i);
    }
    dfs(1);
    for(int i=0;i<euler.size();i++){
        dp[i][0]=euler[i];
    }
    for(int i=2;i<=euler.size();i++){
        log_2[i]=log_2[i/2]+1;
    }
    for(int i=euler.size()-1;i>=0;i--){
        for(int j=1;i+(1<<j)-1<=euler.size()-1;j++){
            if(nivel[dp[i][j-1]]<nivel[dp[i+(1<<(j-1))][j-1]]){
                dp[i][j]=dp[i][j-1];
            }else{
                dp[i][j]=dp[i+(1<<(j-1))][j-1];
            }
        }
    }
    int a,b,l;
    for(int i=1;i<=m;i++){
        cin>>a>>b;
        a=poz[a];
        b=poz[b];
        if(a>b){
            swap(a,b);
        }
        l=log_2[b-a+1];
        if(nivel[dp[a][l]]<nivel[dp[b-(1<<l)+1][l]]){
            cout<<dp[a][l]<<'\n';
        }else{
            cout<<dp[b-(1<<l)+1][l]<<'\n';
        }
    }
}*/

#include <fstream>
#include <vector>
using namespace std;
ifstream cin("lca.in");
ofstream cout("lca.out");
//in dp[j][i] imi retin al 2^j stramos al lui i
//fac dfs ca sa determin nivelurile nodurilor
//dupa fac stramosi
//stiu tatal direct al fiecarui nod
//dp[0][i]=nr 
//ma asigur ca ma aflu pe acelasi nivel
//si dupa fac algoritmul de stramosi
const int MAXVAL=1e5,putere=20;
vector<vector<int>>gr(MAXVAL+1);
int dp[putere+1][MAXVAL+1],log_2[MAXVAL+1],nivel[MAXVAL+1];
void dfs(int nod){
    for(const auto&x:gr[nod]){
        nivel[x]=nivel[nod]+1;
        dfs(x);
    }
}
int main(){
    int n,m,nr;
    cin>>n>>m;
    for(int i=2;i<=n;i++){
        cin>>nr;
        gr[nr].push_back(i);
        dp[0][i]=nr;
    }
    for(int i=2;i<=n;i++){
        log_2[i]=log_2[i/2]+1;
    }
    for(int j=1;j<=log_2[n];j++){
        for(int i=1;i<=n;i++){
            dp[j][i]=dp[j-1][dp[j-1][i]];
        }
    }
    dfs(1);
    int a,b,dif;
    for(int i=1;i<=m;i++){
        cin>>a>>b;
        if(nivel[a]>nivel[b]){
            dif=nivel[a]-nivel[b];
            while(dif){
                a=dp[log_2[dif]][a];
                dif-=1<<log_2[dif];
            }
        }else if(nivel[a]<nivel[b]){
             dif=nivel[b]-nivel[a];
               while(dif){
                b=dp[log_2[dif]][b];
                dif-=1<<log_2[dif];
            }
        }

        if(a==b){
            cout<<a<<'\n';
            continue;
        }
       for(int i=log_2[nivel[a]];i>=0;i--){
            if(dp[i][a]!=dp[i][b]){
                  a=dp[i][a];
                  b=dp[i][b];
            }
       }
        cout<<dp[0][a]<<'\n';
    }
}