Cod sursa(job #1221275)

Utilizator mihai995mihai995 mihai995 Data 19 august 2014 23:57:52
Problema Lowest Common Ancestor Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 2.75 kb
#include <fstream>
#include <cstdlib>
using namespace std;

const int N = 2e5, B = 4, LG = 18 - B;

class FastLCA{
    int rmq[LG][N >> B];
    int *bro, *son, *depth, *euler, *S, *D, *poz;

    inline int best(int x, int y){
        return depth[x] < depth[y] ? x : y;
    }

    inline int best(int x, int y, int z, int t){
        return best( best(x, y), best(z, t) );
    }

    void dfs(int x){
        euler[ ++euler[0] ] = x;
        poz[x] = euler[0];
        for (int y = son[x] ; y ; y = bro[y]){
            depth[y] = 1 + depth[x];
            dfs(y);
            euler[ ++euler[0] ] = x;
        }
    }
public:
    void buildTree(int T[], int n){
        poz = (int*)calloc(n + 1, sizeof(int));
        depth = (int*)calloc(n + 1, sizeof(int));
        euler = (int*)calloc(2 * n, sizeof(int));
        S = bro = (int*)calloc(2 * n + 1, sizeof(int));
        D = son = (int*)calloc(2 * n + 1, sizeof(int));

        for (int i = 2 ; i <= n ; i++){
            bro[i] = son[ T[i] ];
            son[ T[i] ] = i;
        }

        dfs(1);

        S[0] = D[0] = 0;
        depth[0] = n;

        int mask = (1 << B) - 1;
        for (int i = euler[0] ; i ; i--)
            if (i & mask)
                S[i] = best(S[i + 1], euler[i]);
            else
                S[i] = euler[i];
        for (int i = 1 ; i <= euler[0] ; i++)
            if ( i & mask )
                D[i] = best(D[i - 1], euler[i]);
            else
                D[i] = euler[i];

        int size = euler[0] >> B;
        for (int i = 0 ; i < size ; i++)
            rmq[0][i] = D[ (i << B) ^ mask ];
        rmq[0][size] = D[ euler[0] ];

        for (int i = 1, step = 1 ; i < LG ; i++)
            for (int j = 0 ; j <= size ; j++)
                rmq[i][j] = best(rmq[i - 1][j], rmq[i - 1][j + step]);
    }

    inline int lca(int x, int y){
        x = poz[x];
        y = poz[y];

        if (x > y)
            swap(x, y);

        if ( (x >> B) == (y >> B) ){
            int ans = 0;
            for (int i = x ; i <= y ; i++)
                ans = best(ans, euler[i]);
            return ans;
        }

        if ( (y >> B) == (x >> B) + 1 )
            return best(S[x], D[y]);

        int L = 31 - __builtin_clz( (y >> B) - (x >> B) - 1);
        return best( S[x], rmq[L][1 + (x >> B)], rmq[L][(y >> B) - (1 << L)], D[y] );
    }
};

FastLCA tree;
int T[N], n;

int main(){
    ifstream in("lca.in");
    ofstream out("lca.out");

    int nrQ, x, y;

    in >> n >> nrQ;
    for (int i = 2 ; i <= n ; i++)
        in >> T[i];
    tree.buildTree(T, n);

    while (nrQ--){
        in >> x >> y;
        out << tree.lca(x, y) << '\n';
    }

    out.close();
    in.close();

    return 0;
}