Cod sursa(job #1333473)

Utilizator vlady1997Vlad Bucur vlady1997 Data 3 februarie 2015 10:59:50
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.24 kb
        #include <cstdio>
        #include <vector>
        using namespace std;
        vector <int> g[100001];
        int euler[1000001], nivel[1000001], poz[1000001], d[21][200001], lg[200001], nr=1;
        void RMQ (void)
        {
            int i, j;
            for (i=1; i<=nr; i++) d[0][i]=i;
            for (i=2; i<=nr; i++) lg[i]=lg[i/2]+1;
            for (i=1; (1<<i)<=nr; i++)
            {
                for (j=1; j<=nr-(1<<i)+1; j++)
                {
                    d[i][j]=min(d[i-1][j],d[i-1][j+(1<<(i-1))]);
                    if (nivel[d[i-1][j]]<nivel[d[i-1][j+(1<<(i-1))]]) d[i][j]=d[i-1][j];
                    else d[i][j]=d[i-1][j+(1<<(i-1))];
                }
            }
        }
        void dfs (int x, int p)
        {
            int i;
            for (i=0; i<g[x].size(); i++)
            {
                euler[++nr]=g[x][i];
                nivel[nr]=p+1;
                poz[g[x][i]]=nr;
                dfs(g[x][i],p+1);
                euler[++nr]=x;
                nivel[nr]=p;
            }
        }
        int lca (int p, int r)
        {
            int x=poz[p], y=poz[r], dif, k, sol;
            if (x>y)
            {
                int aux=x;
                x=y; y=aux;
            }
            dif=y-x+1;
            k=lg[dif];
            if (nivel[d[k][x]]<nivel[d[k][x+dif-(1<<k)]]) sol=d[k][x];
            else sol=d[k][x+dif-(1<<k)];
            if (euler[sol]!=0) return euler[sol];
            else return 1;
        }
        int main()
        {
            int n, m, i, x, y;
            freopen("lca.in","r",stdin);
            freopen("lca.out","w",stdout);
            scanf("%d%d",&n,&m); euler[1]=1; nivel[1]=0; poz[1]=1;
            for (i=2; i<=n; i++)
            {
                scanf("%d",&x);
                g[x].push_back(i);
            }
            dfs(1,0);
            RMQ();
            for (i=1; i<=m; i++)
            {
                scanf("%d%d",&x,&y);
                printf("%d\n",lca(x,y));
            }
            return 0;
        }
//euler 1 2 4 7 4 8 4 2 5 2 6 9 6 2 1 3 10 3 11 3 1
//nivel 0 1 2 3 2 3 2 1 2 1 2 3 2 1 0 1 2 1 2 1 0
//poz   1 2 16 3 9 11 4 6 12 17 19
//      1 2  3 4 5  6 7 8  9 10 11