Cod sursa(job #3309751)

Utilizator matei__bBenchea Matei matei__b Data 8 septembrie 2025 14:06:20
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.79 kb
#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int NMAX=4e5+8;

ifstream fin("lca.in");
ofstream fout("lca.out");

int n,m;
vector<int> g[NMAX];
int a[NMAX];
int depth[NMAX],st[NMAX],euler[NMAX],timer;
int anc[NMAX];
ll sp[NMAX];
int rmq[19][NMAX];
int lg[NMAX];

void read()
{
    fin >> n;
    for(int i=1; i<n; i++)
    {
        int x,y;
        fin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    fin >> m;
    for(int i=1; i<=m; i++)
        fin >> a[i];
}

void dfs(int nod,int daddy,int h)
{
    depth[nod]=h;
    ++timer;
    st[nod]=timer;
    euler[timer]=nod;

    for(auto it:g[nod])
    {
        if(it==daddy)
            continue;
        dfs(it,nod,h+1);
        euler[++timer]=nod;
    }
}

void pre()
{
    lg[0]=-1;
    for(int i=1; i<=timer; i++)
    {
        lg[i]=1+lg[i/2];
        rmq[0][i]=euler[i];
    }

    for(int i=1; (1<<i)<=timer; i++)
    {
        for(int j=1; j<=timer-(1<<i)+1; j++)
        {
            int l(1<<(i-1));
            if(depth[rmq[i-1][j]]<depth[rmq[i-1][j+l]])
                rmq[i][j]=rmq[i-1][j];
            else   
                rmq[i][j]=rmq[i-1][j+l];
        }
    }
}

int lca(int x,int y)
{
    int len=abs(st[x]-st[y])+1;
    int l=lg[len];
    int sh=len-(1<<l);  

    if(depth[rmq[l][min(st[x],st[y])]]<depth[rmq[l][min(st[x],st[y])+sh]])
        return rmq[l][min(st[x],st[y])];
    return rmq[l][min(st[x],st[y])+sh];
}

ll solve(int st,int dr)
{
    if(st==dr)
        return (ll)a[st];

    int mij=st+(dr-st)/2;
    ll ans=solve(st,mij)+solve(mij+1,dr);

    anc[mij]=a[mij];
    for(int i=mij-1; i>=st; i--)
        anc[i]=lca(anc[i+1],a[i]);
    anc[mij+1]=a[mij+1];
    for(int i=mij+2; i<=dr; i++)
        anc[i]=lca(anc[i-1],a[i]);
    sp[dr]=anc[dr];
    for(int i=dr-1; i>mij; i--)
        sp[i]=sp[i+1]+anc[i];

    for(int i=st; i<=mij; i++)
    {
        int l=mij+1,r=dr;
        int u=0;
        while(l<=r)
        {
            int mid=l+(r-l)/2;
            if(anc[mid]==lca(anc[mid],anc[i]))
            {
                u=mid;
                r=mid-1;
            }
            else
                l=mid+1;
        }

        ans+=sp[u];
        if(u)
            ans+=(1LL*anc[i]*(u-mij-1));
    }
    return ans;
}

int main()
{
    ios_base::sync_with_stdio(false);
    fin.tie(nullptr);
    fout.tie(nullptr);

    //ead();

    fin >> n >> m;
    for(int i=1; i<n; i++)
    {
        int x;
        fin >> x;
        g[x].push_back(i+1);
        g[i+1].push_back(x);
    }
    dfs(1,0,0);
    pre();

    while(m--)
    {
        int x,y;
        fin >> x >> y;
        fout << lca(x,y) << "\n";
    }

    //cout << solve(1,m);

    return 0;
}