Cod sursa(job #2848988)

Utilizator 100pCiornei Stefan 100p Data 14 februarie 2022 12:43:59
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.22 kb
#include <bits/stdc++.h>
#define ull unsigned long long
#define FILES freopen("lca.in","r",stdin);\
              freopen("lca.out","w",stdout);
#define CMAX 15485863
#define fastio std::ios_base::sync_with_stdio(NULL),cin.tie(NULL),cout.tie(NULL);
#define mp make_pair
#define INF 1e18
#define mod 3000017
#define ll long long
#define SMAX 300
#define MAX 1000000
#define pb push_back
#define add emplace_back
#define void inline void

using namespace std;
int n,q,cnt,f[MAX+5];
pair<int,int> rmq[MAX+5][22];
bool check[MAX+5];
vector<int> v[MAX/10+5];
pair<int,int> dp[MAX+5];
void dfs(int x,int h)
{
    cnt++;
    dp[cnt].first = x,dp[cnt].second = h;
    f[x] = cnt;
    for(auto i : v[x])
    {
        if(!check[i])
        {
            check[i] = 1;
            dfs(i,h+1);
            cnt++;
            dp[cnt].first = x, dp[cnt].second = h;
        }
    }
}
int main()
{
    fastio
    FILES
    cin >> n >> q;
    for(int i = 1; i < n; ++i)
    {
        int a,b;
        cin >> a;
        v[a].add(i+1),v[i+1].add(a);
    }
    check[1] = 1;
    dfs(1,0);
    int r = log2(cnt);
    int x = cnt;
    for(int i = 1; i <= MAX; ++i)
        for(int j = 0; j <= 21; ++j) rmq[i][j] = {1e9,1e9};
    for(int i = 1; i <= cnt; ++i) rmq[i][0] = dp[i];
    for(int i = 1; i <= r; ++i)
    {
        x -= (1 << (i - 1));
        int u = (1 << (i - 1));
        for(int j = 1; j <= x; ++j)
        {
            if(rmq[j][i-1].second > rmq[j+u][i-1].second)
            {
                rmq[j][i].second = rmq[j+u][i-1].second;
                rmq[j][i].first = rmq[j+u][i-1].first;
            }
            else
            {
                rmq[j][i].second = rmq[j][i-1].second;
                rmq[j][i].first = rmq[j][i-1].first;
            }
        }
    }
    for(int i = 1; i <= q; ++i)
    {
        int a,b;
        cin >> a >> b;
        int dif = max(f[a],f[b]) - min(f[a],f[b]) + 1;
        int p = 1,e = 0;
        while(p <= dif) p *= 2,e++;
        p >>= 1,e--;
        int fr = min(f[a],f[b]);
        if(rmq[fr][e].second > rmq[fr+(1<<e)-1][e].second)
            cout << rmq[fr+(1<<e)-1][e].first << '\n';
        else cout << rmq[fr][e].first << '\n';
    }
}