Cod sursa(job #3232694)

Utilizator cosmin_varlanVarlan Nicolae Cosmin cosmin_varlan Data 1 iunie 2024 09:13:11
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.04 kb
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

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

int t[10001];
vector<int> copii[10001];


int n, m;

int pozInE[10001];
int E[10001][2];
int poz=0;


/// de fapt aici ar trebui sa avem dimensiunea aia mare de la E
/// si log2 de acea dimensiune (ca numar de coloane):

int minim[10001][21];
int minim_pos[10001][21];




void construiesteEuler(int nod, int adancime)
{
    if (pozInE[nod]==0) pozInE[nod]=poz;

    E[poz][0] = nod;
    E[poz][1] = adancime;
    poz++;

    for(auto y : copii[nod])
    {
        construiesteEuler(y, adancime+1);
        E[poz][0] = nod;
        E[poz][1] = adancime;
        poz++;
    }
}


int minimInterval(int s, int d){
    if (s==d) return minim[s][0];

    int k=0;
    while((1<<k)+s<=d) k++;
    k--;


    if (s+(1<<k)<d) return min(minim[s][k],minimInterval(s+(1<<k),d));
    else return minim[s][k+1];
}



int pozMinim(int s, int d){
    int k=0;
    while((1<<k)+s<=d) k++;
    k--;

    if (s+(1<<k)<d) return (minim[s][k]<minimInterval(s+(1<<k),d)?minim_pos[s][k]:pozMinim(s+(1<<k),d));
    else return minim_pos[s][k+1];
}



int main()
{
    fin >> n >> m;
    for(int i=2; i<=n; i++)
    {
        fin >> t[i];
        copii[t[i]].push_back(i);
    }

    /*for(int i=1; i<=n; i++)
    {
        fout << i << ' ';
        for(auto y : copii[i])
            fout << y << ' ';
        fout << '\n';
    }
    */

    construiesteEuler(1,0); /// aici poti pune "tatal"

    for(int i=0; i<poz; i++)
    {
        minim[i][0]=E[i][1];
        minim_pos[i][0]=i;
    }

    for(int k=1; k<8; k++)
    {
        for(int i=0; i<poz-(1<<(k-1)); i++)
        {
            minim[i][k] = min(minim[i][k-1],minim[i+(1<<(k-1))][k-1]);
            minim_pos[i][k] = (minim[i][k-1] <= minim[i+(1<<(k-1))][k-1] ? minim_pos[i][k-1] : minim_pos[i+(1<<(k-1))][k-1]);
        }
    }

    for(int interval=0; interval<m; interval++)
    {
        int x,y;
        fin >> x >> y;
        if (pozInE[x]>pozInE[y]) swap(x,y);
        //fout << E[pozMinim(pozInE[x], pozInE[y])-1][0] << endl;
        //fout << pozMinim(pozInE[x], pozInE[y]) << endl;
        //fout << x << " este in pozitia " << pozInE[x] << endl;
        //fout << y << " este in pozitia " << pozInE[y] << endl;



        //fout << "intre " << pozInE[x] << " si " << pozInE[y] << " minimul este " << minimInterval(pozInE[x],pozInE[y]) << " si e pe pozitia " << pozMinim(pozInE[x],pozInE[y]) << endl;
        fout << E[pozMinim(pozInE[x],pozInE[y])][0] << endl;
    }


    //fout << endl;


//    for(int i=0; i<30; i++)
//    {
//        for(int j=0; j<8; j++)
//            cout << minim[i][j] << '['<< (minim_pos[i][j]<10?" ":"")<< minim_pos[i][j] <<']'<< "   ";
//        cout << endl;
//    }




//
//    for(int i=0; i<poz; i++)
//        fout <<i << " - "<< E[i][0] << ' ' << E[i][1] << endl;

    //for(int i=0; i<poz; i++)
    //    fout << E[i][1] << endl;
    return 0;
}