Cod sursa(job #2449227)

Utilizator voyagerSachelarie Bogdan voyager Data 18 august 2019 21:17:27
Problema Lowest Common Ancestor Scor 30
Compilator py Status done
Runda Arhiva educationala Marime 1.53 kb
#!/usr/bin/env python3

import sys

sys.stdout = open('lca.out', 'w')

with open('lca.in', 'r') as f:
    readInts = lambda: map(int, f.readline().split())

    N, M = tuple(readInts())
    N += 1
    edges = [[] for _ in range(N)]
    lvl = [-1] * N
    euler = []
    pos = [-1] * N
    parent = list(readInts())
    for i, p in enumerate(parent):
        edges[p].append(i + 2)

    crtNode, crtLvl = 1, 0
    while True:
        lvl[crtNode] = crtLvl
        if pos[crtNode] < 0: pos[crtNode] = len(euler)
        euler.append(crtNode)

        if edges[crtNode]:
            crtNode = edges[crtNode].pop()
            crtLvl += 1
        else:
            if crtLvl == 0: break
            crtLvl -= 1
            crtNode = parent[crtNode - 2]

    E, LOG = len(euler), 0
    while 1 << (LOG + 1) < E: LOG += 1
    RMQ = [[i] * (LOG + 1) for i in range(E)]

    for j in range(1, LOG + 1):
        for i in range(E):
            jPow = 1 << (j - 1)
            if i + jPow * 2 > E: break
            RMQ[i][j] = RMQ[i][j - 1] if lvl[euler[RMQ[i][j-1]]] < lvl[euler[RMQ[i + jPow][j-1]]] else RMQ[i + jPow][j - 1]
    
    def findMin(l, r):
        l, r = min(l, r), max(l, r)
        logDiff = 0
        while 1 << (logDiff + 1) < r - l + 1: logDiff += 1
        if lvl[euler[RMQ[l][logDiff]]] < lvl[euler[RMQ[r - (1 << logDiff) + 1][logDiff]]]:
            return euler[RMQ[l][logDiff]]
        else:
            return euler[RMQ[r - (1 << logDiff) + 1][logDiff]]

    for _ in range(M):
        x, y = tuple(readInts())
        print(findMin(pos[x], pos[y]))