Cod sursa(job #2341326)

Utilizator victorv88Veltan Victor victorv88 Data 11 februarie 2019 19:05:53
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.98 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
using namespace std;

ifstream f("lca.in");
ofstream g("lca.out");

int n, m, query_left, query_right, kid, euler[200010], height[200010], ind=1, lvl;
int first[100005], sp[200005][20], val_log;
vector<int>kids[100005];

void create_euler(int node)
{
    if (first[node]==0)
    {
        first[node]=ind;
    }
    euler[ind]=node;
    height[ind++]=lvl;
    if (kids[node].empty())
    {
        return;
    }
    for (auto &v:kids[node])
    {
        lvl++;
        create_euler(v);
        lvl--;
        euler[ind]=node;
        height[ind++]=lvl;
    }
}

void create_sp()
{
    int size_rmq=2*n-1;
    val_log=(int)log2(size_rmq);
    for (int i=1; i<=size_rmq; i++)
    {
        sp[i][0]=i;
    }
    for (int j=1; j<=val_log; j++)
    {
        int val_dif=1<<j;
        for (int i=1; i<=size_rmq-val_dif+1; i++)
        {
            if (height[sp[i][j-1]]<height[sp[i+(1<<(j-1))][j-1]])
                sp[i][j]=sp[i][j-1];
            else
                sp[i][j]=sp[i+(1<<(j-1))][j-1];
        }
    }
   /* for (int i=1; i<=size_rmq; i++)
    {
        for (int j=0; j<=val_log; j++)
        {
            cout << sp[i][j] <<' ';
        }
        cout << '\n';
    }*/
}

int find_min(int left, int right)
{
    int val_left=first[left];
    int val_right=first[right];
    int dif=val_right-val_left+1;
    int val_log=(int)log2(dif);
    if (val_right<val_left)
        swap(val_left,val_right);
    int val_rmq_1=sp[val_left][val_log];
    int val_rmq_2=sp[val_right-(1<<(val_log))][val_log];
    if (height[val_rmq_1]<height[val_rmq_2])
    {
        return euler[val_rmq_1];
    }
    return euler[val_rmq_2];
}

int main() {
    f >> n >> m;
    for (int i=2; i<=n; i++)
    {
        f >> kid;
        kids[kid].push_back(i);
    }
    create_euler(1);
    create_sp();
    for (int query=0; query<m; ++query)
    {
        f >> query_left >> query_right;
        g << find_min(query_left,query_right) << '\n';
    }
    return 0;
}