Cod sursa(job #2886184)

Utilizator pctirziuTirziu Petre pctirziu Data 7 aprilie 2022 11:14:21
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.17 kb
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;
ifstream cin("lca.in");
ofstream cout("lca.out");
const int nmax = 3e5 + 5;
int rmq[20][nmax], inveuler[nmax], depth[nmax];
pair <int, int> v[nmax];
vector <int> euler;
vector <int> edge[nmax];
bool cmp(pair <int, int> a, pair <int, int> b)
{
    return a.first < b.first;
}
void dfs(int node, int father)
{
    depth[node] = depth[father] + 1;
    euler.push_back(node);
    for(int i = 0; i < edge[node].size(); i++){
        if(edge[node][i] == father)
            continue;
        dfs(edge[node][i], node);
        euler.push_back(node);
    }
}
void rmqcalc()
{
    depth[0] = nmax + 1;
	for(int i = 0; i < euler.size(); i++) {
		rmq[0][i] = euler[i];
		inveuler[euler[i]] = i;
	}
	for(int level = 1; level < 20; level++) {
		for(int i = 0; i + (1 << level) <= euler.size(); i++) {
			int a = rmq[level - 1][i];
			int b = rmq[level - 1][i + (1 << (level - 1))];
			if(depth[a] > depth[b]) rmq[level][i] = b;
			else rmq[level][i] = a;
		}
	}
}
int lca(int a, int b)
{
    a = inveuler[a];
    b = inveuler[b];
    if(a == b)
        return rmq[0][a];
    if(a > b)
        swap(a, b);
    int len = b - a + 1;
    int lg = 31 - __builtin_clz(len);
    if(depth[rmq[lg][a]] > depth[rmq[lg][b - (1 << lg) + 1]])
        return rmq[lg][b - (1 << lg) + 1];
    else
      return rmq[lg][a];
}
void reinitializare()
{
    int maxx = 0, i, j;
    for(j = 1; (1 << j) <= euler.size(); j++)
        for(i = 0; i + (1 << j) + 1 <= euler.size(); i++)
            rmq[j][i] = 0;
    for(i = 0; i < euler.size(); i++){
        inveuler[euler[i]] = 0;
        depth[euler[i]] = 0;
        maxx = max(maxx, euler[i]);
    }
    for(i = 0; i <= maxx; i++)
        edge[i].clear();
    euler.clear();
}
int main()
{
    int n, i, j, t, q;
    cin >> n >> q;
    for(i = 2; i <= n; i++){
        int x;
        cin >> x;
        edge[i].push_back(x);
        edge[x].push_back(i);
    }
    dfs(1, 1);
    rmqcalc();
    for(i = 1; i <= q; i++){
        int a, b;
        cin >> a >> b;
        cout << lca(a, b) << "\n";
    }
    /*cin >> t;
    while(t--){
        cin >> n;
        bool ok = true;
        for(i = 1; i <= n; i++)
            cin >> v[i].first, v[i].second = i;
        for(i = 1; i <= n - 1; i++){
            int x, y;
            cin >> x >> y;
            edge[x].push_back(y);
            edge[y].push_back(x);
        }
        dfs(1, 1);
        rmqcalc();
        /*int q;
        cin >> q;
        for(i = 1; i <= q; i++){
            int a, b;
            cin >> a >> b;
            cout << lca(a, b) << "\n";
        }
        sort(v + 1, v + n + 1, cmp);
        for(i = 2; i <= n; i++){
            if(v[i].first == v[i - 1].first){
                ok = false;
                break;
            }
            int x = lca(v[i].second, v[i - 1].second);
            if(depth[v[i].second] - depth[x] + depth[v[i - 1].second] - depth[x] > v[i].first - v[i - 1].first){
                ok = false;
                break;
            }
        }
        cout << ok;
        reinitializare();
    }*/
    return 0;
}