Cod sursa(job #2203759)

Utilizator emanuel_rRamneantu Emanuel emanuel_r Data 13 mai 2018 03:09:56
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.87 kb
#include <bits/stdc++.h>

using namespace std;

template <typename T>
class LCA{
public:
    vector<vector<pair<int, T> > > &G;
    function<T(T,T)> func;
    vector<int> L, Log, use;
    vector<vector<int> > A;
    vector<vector<T> > V;
    bool indexed;
    int n, root;
    T acc;

    LCA(int n, int root, decltype(G)& Graph, bool idx, function<T(T,T)> f, T acc) :
            G(Graph), func(f), L(n+1), use(n+1), A(n+1), V(n+1), indexed(idx), n(n), root(root), acc(acc) {};

    void dfs(int node, int father, T cost){
        L[node] = L[father] + 1;
        A[node].emplace_back(father);
        V[node].emplace_back(cost);
        use[node] = 1;

        for(auto& it : G[node])
            if(!use[it.first])
                dfs(it.first, node, it.second);
    }

    void build() {
        dfs(root, root, 0);

        Log.emplace_back(0);
        Log.emplace_back(0);
        for(int i = 2; i <= n; i++)
            Log.emplace_back(Log[i/2] + 1);

        if(indexed == 1) {
            A[0].emplace_back(0);
            V[0].emplace_back(acc);
        }

        for(int step = 1; step <= Log[n]; step++)
            for(int i = 0; i < n + indexed; i++) {
                A[i].emplace_back(A[A[i][step - 1]][step - 1]);
                V[i].emplace_back(func(V[i][step - 1], V[V[i][step - 1]][step - 1]));
            }
    }

    int simpleQuery(int x, int y){
        if(L[x] < L[y])
            swap(x, y);
        int maxstep, diff;
        T fold = acc;
        while(L[x] > L[y]){
            diff = L[x] - L[y];
            maxstep = Log[diff];
            x = A[x][maxstep];
        }
        for(int step = Log[L[x]]; step >= 0; step--){
            if(A[x][step] == A[y][step])
                continue;
            x = A[x][step];
            y = A[y][step];
        }
        if(x != y)
            x = A[x][0];
        return x;
    }

    pair<int, T> query(int x, int y){
        if(L[x] < L[y])
            swap(x, y);
        int maxstep, diff;
        T fold = acc;
        while(L[x] > L[y]){
            diff = L[x] - L[y];
            maxstep = Log[diff];
            fold = func(V[x][maxstep], fold);
            x = A[x][maxstep];
        }
        for(int step = Log[L[x]]; step >= 0; step--){
            if(A[x][step] == A[y][step])
                continue;
            fold = func(V[x][step], fold);
            fold = func(V[y][step], fold);
            x = A[x][step];
            y = A[y][step];
        }
        if(x != y){
            fold = func(V[x][0], fold);
            fold = func(V[y][0], fold);
            x = A[x][0];
        }
        return make_pair(x, fold);
    }
};

vector<vector<pair<int, bool> > > G;
LCA<bool> *L;
int n, m, pos;
int const Buffer_Size = 100005;
char Buffer[Buffer_Size];

void read(int& nr){
    nr = 0;
    while(Buffer[pos] > '9' or Buffer[pos] < '0'){
        pos++;
        if(pos == Buffer_Size){
            pos = 0;
            fread(Buffer, 1, Buffer_Size, stdin);
        }
    }
    while(Buffer[pos] <= '9' and Buffer[pos] >= '0'){
        nr = nr*10 + Buffer[pos++] - '0';
        if(pos == Buffer_Size){
            pos = 0;
            fread(Buffer, 1, Buffer_Size, stdin);
        }
    }
}

int main()
{
    ios_base::sync_with_stdio(false);
    //freopen("i.in", "r", stdin);
    freopen("lca.in", "r", stdin);
    freopen("lca.out", "w", stdout);
    fread(Buffer, 1, Buffer_Size, stdin);

    read(n);
    read(m);
    int t;
    G.resize(n + 1);

    for(int i = 2; i <= n; i++){
        read(t);
        G[t].emplace_back(i, 0);
    }

    L = new LCA<bool>(n, 1, G, 1, [](bool a, bool b){return 0;}, 0);
    L->build();

    int x, y;
    int ance;

    for(int i = 1; i <= m; i++){
        read(x);
        read(y);
        ance = L->simpleQuery(x, y);
        printf("%d\n", ance);
    }
    return 0;
}