Cod sursa(job #2966902)

Utilizator raulandreipopRaul-Andrei Pop raulandreipop Data 18 ianuarie 2023 17:44:20
Problema Lowest Common Ancestor Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.09 kb
#include <iostream>
#include <vector>

#define aintNull 0
#define aintData int

using namespace std;



struct AINT {
    int offset;
  //  int n;
    vector<int> aint;

    aintData merge (aintData a, aintData b)
    {
        aintData par;
        par = max(a, b);
        return par;
    }

    void build (int nod, int l, int r, vector<aintData>& a)
    {
        if (l >= a.size()) return;
        if (l == r){
            aint[nod] = a[l];
            return;
        }
        int m = (l + r) / 2;
        build(2 * nod, l, m, a);
        build(2 * nod + 1, m + 1, r, a);
        aint[nod] = merge(aint[2 * nod], aint[2 * nod + 1]);
    }

    void buildLin (vector<aintData>& a)
    {
        for (int i = offset; i < 2 * offset; i++)
        {
            aint[i] = a[i - offset + 1];
        }
        for (int i = offset - 1; i > 0; i--)
        {
            aint[i] = merge(aint[2 * i], aint[2 * i + 1]);
        }
    }
    
    void initialize(int n, vector<aintData>& a)
    {
        offset = 1;
        while (offset < n) offset *= 2;
        aint.resize(2 * offset + 1);
        buildLin(a);
    }

    void upd (int nod, int l, int r, int pos, int val)
    {
        if (l == r)
        {
            if (l == pos) {
                aint[nod] = val;
            }
            return;
        }
        if (l > pos || r < pos) return;
        
        int m = (l + r) / 2;
        if (m >= pos) upd(2 * nod, l, m, pos, val);
        else upd(2 * nod + 1, m + 1, r, pos, val);
        aint[nod] = merge(aint[2 * nod], aint[2 * nod + 1]);
    }

    void updLin (int pos, int val)
    {
        int updPos = pos + offset - 1;
        aint[updPos] = val;
        updPos /= 2;
        while (updPos > 0)
        {
            aint[updPos] = merge(aint[2 * updPos], aint[2 * updPos + 1]);
            updPos /= 2;
        }
    }

    void update (int pos, int val)
    {
      //  upd(1, 1, offset, pos, val);
        updLin(pos, val);
    }

    aintData qry (int nod, int l, int r, int ql, int qr)
    {
        if (ql <= l && r <= qr)
        {
            return aint[nod];
        }
        if (r < ql || l > qr) return aintNull;
        int m = (l + r) / 2;
        return merge(qry(2 * nod, l, m, ql, qr), 
        qry(2 * nod + 1, m + 1, r, ql, qr));
    }

    aintData query(int l, int r)
    {
        return qry(1, 1, offset, l, r);
    }

};

const int nmax = 1e5 + 9;
int v[nmax];
int p[nmax];

struct HLD {
    vector<int> adj[nmax];
  //  AINT aint;
    int n;
    int subtree[nmax];
    int heavyChild[nmax];
    vector<int> heavyOrder;
    int heavyHead[nmax];
    int depth[nmax];
    int parent[nmax];

    void calcSubtree (int nod = 1, int par = 0)
    {
        parent[nod] = par;
        subtree[nod] = 1;
        depth[nod] = depth[par] + 1;
        int maxSon = 0, sonInd = -1;
        for (int to : adj[nod])
        {
            if (to == par) continue;
            calcSubtree(to , nod);
            subtree[nod] += subtree[to];
            if (subtree[to] > maxSon)
            {
                maxSon = subtree[to];
                sonInd = to;
            }
        }
        heavyChild[nod] = sonInd;
    }

    void heavyFirst (int nod, int par, int head)
    {
        heavyHead[nod] = head;
        heavyOrder.push_back(nod);
        if (heavyChild[nod] != -1) heavyFirst(heavyChild[nod] , nod, head);
        for (auto to : adj[nod])
        {
            if (to != heavyChild[nod] && to != par)
            {
                heavyFirst(to , nod, to);
            }
        }
    }
    void printHeavyOrder ()
    {
        for (int i = 1; i <= n; i++)
        {
            cout << heavyOrder[i] << ' ';
        }
        for (int i = 1; i <= n; i++)
        {
            cout << i << ' ' << heavyHead[i] << '\n';
        }
        cout << '\n';
    }
    
    void initialize(int N)
    {
        n = N;
     //   int time = 0;
        heavyOrder.push_back(0);
        
        calcSubtree();
        heavyFirst(1, 0, 1);

      //  aint.initialize(n, a);
    }

    int lca (int u, int v)
    {
        if (heavyHead[u] == heavyHead[v]) {
            if (depth[u] < depth[v]) return u;
            else return v;
        }
        if (depth[heavyHead[u]] < depth[heavyHead[v]])
        {
            return lca(parent[heavyHead[v]] , u);
        }
        else {
            return lca(parent[heavyHead[u]] , v);
        }
    }

    int query (int x, int y)
    {

    }
};

int main ()
{
    freopen("lca.in" , "r" , stdin);
    freopen("lca.out" , "w" , stdout);
    int n , q; cin >> n >> q;
    
    HLD hld;
    for (int i = 2; i <= n; i++)
    {
        cin >> p[i];
        hld.adj[p[i]].push_back(i);
    }
    hld.initialize(n);

    while (q--)
    {
        int x, y; cin >> x >> y;
        cout << hld.lca(x, y) << '\n';
    }

  /*  for (int i = 1; i < n; i++)
    {
        int x, y; cin >> x >> y;
        hld.adj[x].push_back(y);
        hld.adj[y].push_back(x);
    }*/
  //  hld.printHeavyOrder();
    
}