Cod sursa(job #2772700)

Utilizator RamanujanNeacsu Mihnea Ramanujan Data 2 septembrie 2021 13:08:40
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.36 kb
#include <fstream>
#include <vector>
#include <queue>

const int maxn=1e5+2;
const int inalt=19;
using namespace std;

ifstream cin ("lca.in");
ofstream cout ("lca.out");

int dads[maxn], depth[maxn], findNode[maxn];
vector<int> sons[maxn];
vector<int> linear;//aici tinem liniarizarea; impingem elementele unul cate unul
void dfs(int i){
    linear.push_back(i);
    findNode[i]=linear.size()-1;
    for(int j=0; j<sons[i].size(); j++){
        depth[sons[i][j]]=depth[i]+1;//cresc in valuri adancimea
        dfs(sons[i][j]);
        linear.push_back(i);//bag noile noduri in vecor de liniarizre
        findNode[i]=linear.size()-1;//si marchez ca sa stiu de unde le iau
    }
}
int rmq[maxn<<1][inalt], powers[inalt+1], floorExponent[maxn<<1];
int query(int lo, int hi){
    int gap=hi-lo+1;
    if(depth[rmq[lo][floorExponent[gap]]]<depth[rmq[hi-powers[floorExponent[gap]]+1][floorExponent[gap]]]){
        return rmq[lo][floorExponent[gap]];
    }
    else
        return rmq[hi-powers[floorExponent[gap]]+1][floorExponent[gap]];
}
int main()  {
    int n, m; cin>>n>>m;
    for(int i=0; i<n-1; i++){
        cin>>dads[i+2];//citim direct tatii
        sons[dads[i+2]].push_back(i+2);
    }
    dfs(1);
    powers[0]=1;
    int index=1;
    while(powers[index-1]<linear.size()){
        powers[index]=powers[index-1]<<1;
        index++;//ne generam puterile lui 2
    }
    floorExponent[1]=0;
    int nextPower=2;
    for(int i=2; i<linear.size(); i++){
        if(i==nextPower){
           floorExponent[i]=floorExponent[i-1]+1;
           nextPower<<=1;
        }
        else
           floorExponent[i]=floorExponent[i-1];
    }
    for(int j=0; j<index; j++){
        for(int i=1; i<=linear.size(); i++){
           if(j==0){//daca avem intervale de lungime 1
             rmq[i][j]=linear[i];//punem direct valoarea
           }
           else{//la alea mai lungi
             if(depth[rmq[i][j-1]]<depth[rmq[min(i+powers[j-1], (int)linear.size())][j-1]])
                rmq[i][j]=rmq[i][j-1];//punem minimul dupa adancimi
             else rmq[i][j]=rmq[min(i+powers[j-1], (int)linear.size())][j-1];
           }
        }
    }
    for(int i=0; i<m; i++){
        int x, y; cin>>x>>y;
        x=findNode[x], y=findNode[y];
        if(x<y)
            swap(x, y);
        cout<<query(y, x)<<"\n";
    }
    return 0;
}