Cod sursa(job #2674043)

Utilizator ptudortudor P ptudor Data 18 noiembrie 2020 15:17:11
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.64 kb
#include<bits/stdc++.h>
#define fore(start,i,end) for(int i = start; i <= end; i++)
#define dbg(x)  #x << "=" << x << " "
#define dbg2(x,y)  "{" << x << "," << y << "} "
#define dbg3(x,y,k) "{" << x << "," << y << "," << k << "} "
#define dbg4(x,y,k,j) "{" << x << "," << y << "," << k << " , " << j << "} "

#define ll long long
#define f1 first
#define f2 second
#define inf 1000000005
#define debug_st(st) if (true) {cout << #st << " : "; stack<int> s123; while (!s123.empty()) cout << s123.top() << " ", s123.pop(); cout << "\n";}
#define debug_a(a,n) cout << #a << " : "; for(int i = 1; i <= n; i++) cout <<  a[i] << " "; cout << "\n";
#define debug_v(v) cout << #v << " : "; for(auto k : v) cout << k << " "; cout << "\n";
#define debug_s(s) cout << #s << " : "; for (auto k : s) cout << k < " "; cout << "\n";
#define debug_s2(s) cout << #s << " : "; for(auto k : s) cout << dbg2((*k).first,(*k).second); cout << "\n";
#define nmax 500005

using namespace std;

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

int tour[nmax],t,first[nmax],n,m,dad[nmax],lastp[ nmax],r[nmax];
vector<int> kids[nmax];
pair<int,int> rmq[nmax][22];

void euler(int nod)
{
    tour[++t] = nod;
    first[nod] = t;
    for (auto k : kids[nod])
    {
        euler(k);
        tour[++t] = nod;
    }
}
void make_rmq()
{int i,l;
    ///init pentru aia singuri
    ///{rank , ind}
    for (i = 1; i <= t; i++) rmq[i][0] = {r[tour[i]] , tour[i]};

    int maxl = log(t) + 1;
    for(l = 1; l <= maxl; l++) {
        for(i = 1; i <= t; i++) {
            if (i + (1 << l) - 1 > t) continue;
            rmq[i][l] = min(rmq[i][l - 1] , rmq[ i + ( 1 << (l - 1) ) ][l - 1] );
        }
    }
}
void get_rank(int nod, int Rank)
{
    r[nod] = Rank;
    for (auto k : kids[nod])
        get_rank(k , Rank + 1);
}
int main()
{int i;
    ///input
    in >> n >> m;
    for (i = 1; i < n; i++) {
        in >> dad[i + 1];
        kids[dad[i + 1]].push_back(i + 1);
    };
    ///get rank for each node
    get_rank(1 , 1);

    //debug_a(r , n);
    ///euler tour and we add every time we finish a subtree for a node (or when entering a node)
    ///find for every when you first come to it.
    euler(1);
   // debug_a(tour , t);

    make_rmq();


    lastp[1] = 0;
    for (i = 2; i <= t; i++)
        lastp[i] = lastp[i / 2] + 1;
    for(i = 1; i <= m; i++)
    {int st,dr;
        in >> st >> dr;
        st = first[st];
        dr = first[dr];
        int l = lastp[dr - st + 1];
       // cout << dbg(i) << dbg(st) << dbg(dr) << dbg(l) << "\n";

        out << min(rmq[st][l] , rmq[dr - (1 << l) + 1][l]).second << "\n";
    }
}