Cod sursa(job #2368044)

Utilizator mihailrazMihail Turcan mihailraz Data 5 martie 2019 13:29:16
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.71 kb
#include <fstream>
#include <vector>

using namespace std;
ifstream fi("lca.in");
ofstream fo("lca.out");
const int nmax=1e5;
int n, m, ne;
int tata[nmax+5], euler[2*nmax+5], level[nmax+5], first[nmax+5], log2[2*nmax+5];
int dp[2*nmax+5][21];
vector <int> G[nmax+5];

void dfs(int nod, int lvl)
{
/// construieste sirurile euler, level si first
    euler[++ne]=nod;
    level[ne]=lvl;
    first[nod]=ne;
    for(auto vec:G[nod])
    {
        dfs(vec, lvl+1);
        euler[++ne]=nod;
        level[ne]=lvl;
    }
}

void rmq(void)
{
/// construieste dp
    log2[1]=0;
    for(int i=2; i<=ne; i++)
        log2[i]=log2[i/2]+1;

    for(int i=1; i<=ne; i++)
        dp[i][0]=i;

    for(int j=1; j<=log2[ne]; j++)
        for(int i=1; i+(1<<j)-1<=ne; i++)
        {
            dp[i][j]=dp[i][j-1];
            if(level[dp[i+(1<<(j-1))][j-1]]<level[dp[i][j]])
                dp[i][j]=dp[i+(1<<(j-1))][j-1];
        }
}

int min_query(int x, int y)
{
/// returneaza indicele elementului minim din intervalul level[x...y]
    if(x>y)
        swap(x, y);
    int range=y-x+1, lg=log2[range];
    if(level[dp[x+(1<<lg)][lg]] < level[dp[y-(1<<lg)+1][lg]])
        return dp[x+(1<<lg)][lg];
    return dp[y-(1<<lg)+1][lg];
}

int lca(int nod1, int nod2)
{
/// returneaza cel mai apropiat stramos comun al nodurilor nod1 si nod2
    return euler[min_query(first[nod1], first[nod2])];
}

int main()
{
    fi>>n>>m;
    for(int i=2; i<=n; i++)
    {
        fi>>tata[i];
        G[tata[i]].push_back(i);
    }
    dfs(1, 0);
    rmq();
    while(m--)
    {
        int u, v;
        fi>>u>>v;
        fo<<lca(u, v)<<"\n";
    }
    fi.close();
    fo.close();
    return 0;
}