Cod sursa(job #3273192)

Utilizator bostanlucastefanBostan Luca-Stefan bostanlucastefan Data 1 februarie 2025 11:24:44
Problema Lowest Common Ancestor Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.65 kb
#include <fstream>
#include <vector>
#define FAST ios_base::sync_with_stdio(false);

using namespace std;

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

const int N=1e5;

int n,q,i,j;
vector<int> g[N+2],first(N);
vector<pair<int,int>> euler;
int rmq[2*N+2][20],log2[2*N+2];

void eulertour(int u,int marked,int depth)
{
    first[u]=euler.size();
    euler.push_back({u,depth});
    for(auto v:g[u])
    {
        if(v==marked)
            continue;
        eulertour(v,u,depth+1);
        euler.push_back({u,depth});
    }
}

void rmq_()
{
    for(i=0; i<euler.size(); i++)
        rmq[i][0]=i;
    for(i=1; (1<<i)<=euler.size(); i++)
        for(j=0; j+(1<<i)-1<euler.size(); j++)
        {
            int stabove=rmq[j][i-1];
            int drabove=rmq[j+(1<<(i-1))-1][i-1];
            if(euler[stabove].second<euler[drabove].second)
                rmq[j][i]=stabove;
            else
                rmq[j][i]=drabove;
        }
}

int lca(int x,int y)
{
    x=first[x];
    y=first[y];
    if(x>y) swap(x,y);

    int lvl=log2[y-x+1];
    int firstcut=rmq[x][lvl];
    int secondcut=rmq[y-(1<<lvl)+1][lvl];
    if(euler[firstcut].second<euler[secondcut].second)
        return euler[firstcut].first;
    return euler[secondcut].first;
}

int main()
{
    FAST
    cin>>n>>q;
    for(i=2; i<=n; i++)
    {
        int x;
        cin>>x;
        g[x].push_back(i);
        g[i].push_back(x);
    }

    eulertour(1,0,0);
    rmq_();
    for(i=2; i<=2*N; i++)
        log2[i]=log2[i/2]+1;

    while(q--)
    {
        int u,v;
        cin>>u>>v;
        cout<<lca(u,v)<<'\n';
    }
    return 0;
}